1

Is there a way for process A (which created a shared memory segment using the POSIX shm_open library - I'm not interested in the SysV shared memory API) to detect that process B has opened the same shared memory segment? I need a way for process A to start "work" after process B has opened the same shared memory. The proposal is for A to poll something until B is connected. (In my case, there are actually 3 processes B1,B2,B3 so I need to wait until all 3 have opened the shared memory).

I've been toying with using lsof /dev/shm/foo and scrape the process IDs, but I'd like to not have to invoke a shell just to do this.

I see other SO answers that solve this problem by creating a semaphore and I could also use some other messaging system, but I was looking for a solution with less moving parts.

Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
  • 2
    `struct shmid_ds *buf` has a variable called `shm_nattch` you can query. You need to call `shmctl` to get this buffer. – cs95 Jul 13 '17 at 23:30
  • @COLDSPEED - thanks, but I need to use the POSIX (aka "Realtime") `shm_open` API, not the System V `shmctl` API. – Mark Lakata Jul 13 '17 at 23:49
  • @MarkLakata I think it will work because it is part of the `POSIX:XSI Extension` and on the man page it clearly state that it is a POSIX conformance. – Seek Addo Jul 14 '17 at 00:16
  • @SeekAddo - The terminology is confusing. Some people call POSIX:XSI "System V", and some people call POSIX:Realtime "POSIX", even though both of them are technically POSIX. I need to use the POSIX:Realtime shared memory, which is not the same as POSIX:XSI (http://man7.org/linux/man-pages/man7/shm_overview.7.html) – Mark Lakata Jul 14 '17 at 16:54

2 Answers2

0

If you wish to have a work start after another maybe you should rely on IPC with signals.

Eg: your process A sends a signal to B that he is ready. B handles the signal and starts processing.

Eventually you can see some process activities on shm_open() file descriptors and mmap() memory mappings within /proc/{pid}/fd/ and /proc/{pid}/maps

Fabien
  • 4,862
  • 2
  • 19
  • 33
0

I came up with this. It avoids making a system call at the cost of a glob call, and dereferencing every /proc/$pid/fd/$fd file to see if it points to the /dev/shm/$name shared memory device.

#include <glob.h>

std::vector<int> GetPids(const std::string& name) const
{
      std::vector<int> result;
      const std::string shmmem = "/dev/shm/" + name;
      const std::string pat("/proc/*/fd/*");

      using namespace std;
      glob_t glob_result;
      glob(pat.c_str(), GLOB_TILDE, NULL, &glob_result);
      vector<string> ret;
      for (unsigned int i = 0; i < glob_result.gl_pathc; ++i)
      {
          char* fd = glob_result.gl_pathv[i];

// std::cout << "checking " << fd << std::endl;

          char fdlink[32];
          ssize_t len = readlink(fd, fdlink, sizeof(fdlink) -1);
          fdlink[len] = 0; // force a null termination
          if (len != -1)
          {
              std::cout <<  fd << " " << fdlink << std::endl;
              if (shmmem == fdlink)
              {
                  int pid = atoi(fd + 6);
                  if (pid != 0 && pid != getpid()) result.push_back(pid);
              }
          }
          else
          {
              perror("readlink failed");
          }
      }
      globfree(&glob_result);
      return result;
} 

This borrows the algorithm from the busybox 'lsof' implementation, except doesn't use the busybox specific library calls.

Mark Lakata
  • 19,989
  • 5
  • 106
  • 123