clinuxposixshared-memoryglibc

How do I correctly determine NAME_MAX for shm_open?


In the manual page for shm_open, we see that the argument for the name parameter should be up to NAME_MAX characters long for portable use.

However, in The GNU C Library Reference Manual's section entitled "Limits on File System Capacity" we see that NAME_MAX is not defined in "limits.h" on a system if it "allows different file systems or files to have different limits. We are told to use pathconf instead.

However, pathconf requires an actual path (or file descriptor) to use. What path should we use for shared memory objects as used by shm_open. From what I understand, this is handled internally by glibc. On Linux, it is often, but not necessarily, "/dev/shm".

I would prefer not to use 255 directly as mentioned in the manual page for shm_open. It doesn't seem like a good idea to just use "/" since "/dev/shm" is often tmpfs, which differs from the root file system.

I tried grepping the header files and the output of getconf -a and looking through other related manual pages, but I don't see anything on how to do this.

I tracked down the code that opens a shared memory object in glibc but that was fairly unhelpful since it's basically hard-coded.

  1. https://github.com/lattera/glibc/blob/master/sysdeps/posix/shm_open.c
  2. https://github.com/lattera/glibc/blob/master/sysdeps/posix/shm-directory.h
  3. https://github.com/lattera/glibc/blob/master/sysdeps/posix/shm-directory.c

Maybe that means I'm underestimating how portable "/dev/shm" is?


Solution

  • In the manual page for shm_open, we see that the argument for the name parameter should be up to NAME_MAX characters long for portable use.

    Yes, it does. And it pretty much lies, as far as the current version of POSIX goes. What POSIX used to say was

    The name argument conforms to the construction rules for a pathname. [...] If name does not begin with the slash character, the effect is implementation-defined. The interpretation of slash characters other than the leading slash character in name is implementation-defined.

    The limitation to NAME_MAX, the maximum length of a path segment, can reasonably be interpreted as implied by name

    as meets requirements and avoids explicit implementation-definedness.

    However, the latest version of POSIX now adds:

    the length limits for the name argument are implementation-defined and need not be the same as the pathname limits {PATH_MAX} and {NAME_MAX}.

    I'm unsure what the point of that change (clarification?) was, as it leaves programmers hanging in the wind, and I don't see how it's much help to implementations.

    Even when we thought we had NAME_MAX to rely on here, however, the relevant portability concern was not the NAME_MAX of the current system, but rather the smallest NAME_MAX of any system on which your code must run. Even if you have more leeway than that on some systems, you need to be prepared to do with the minimum, so you may as well just do that everywhere. That takes runtime pathconf out of the picture.

    Of course, we can't evaluate what NAME_MAX may be on every past, present, and future system. However, the appropriate context for considerations of portable use of this POSIX function is POSIX implementations, and POSIX defines a minimum acceptable value: _POSIX_NAME_MAX, which is 14. Even though that is not conclusive, what you should take from this is that POSIX allows the limit to be very small.

    However, in The GNU C Library Reference Manual's section entitled "Limits on File System Capacity" we see that NAME_MAX is not defined in "limits.h" on a system if it "allows different file systems or files to have different limits.

    If GLibc in fact fails to define NAME_MAX for any particular system then it is not POSIX compliant for that system. POSIX makes some similar comments about the constansts possibly being unsuitable for some uses, but it specifies that they are defined in all cases. But if portability is your aim, however, then it's immaterial. As already described, that requires you to focus on the smallest length limit among all the systems you want to support. If you can be sure of satisfying that then you don't need to perform a runtime check.

    We are told to use pathconf instead.

    Yes and no. POSIX says that it is unspecified whether the names of shared memory objects appear in the filesystem, and pathconf / fpathconf inquire about filesystem characteristics. As long as we're talking about portability, then, we cannot interpret POSIX to be presenting pathconf as a portable means for determining the local limit here. It seems like it might work on systems where those names do appear on the filesystem, but I don't think that Glibc's documentation is necessarily meant to apply to special filesystems such as /dev.

    If you do rely on that, then you're also relying on its existence, which narrows the scope of your portability concerns enough that you probably don't need to go to all the trouble in the first place.

    However, pathconf requires an actual path (or file descriptor) to use. What path should we use for shared memory objects as used by shm_open.

    POSIX does not guarantee that there is any path you can use for that purpose, and that's probably the wrong idea anyway. Keep your shared memory names small, and document the maximum you use. This is a limit on the portability of your program. In practice, you're unlikey to run into any system where 255 bytes is too large, though it's not out of the question that you would do.