+ /*
+ * Try to open read-only again after creation.
+ */
+ wait_shm_fd = shm_open(sock_info->wait_shm_path,
+ O_RDONLY, read_mode);
+ if (wait_shm_fd < 0) {
+ /*
+ * Real-only open did not work. It's a failure
+ * that prohibits using shm.
+ */
+ ERR("Error opening shm %s", sock_info->wait_shm_path);
+ goto end;
+ }
+ goto end;
+ } else if (pid == 0) {
+ int create_mode;
+
+ /* Child */
+ create_mode = S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
+ if (sock_info->global)
+ create_mode |= S_IROTH | S_IWOTH;
+ /*
+ * We're alone in a child process, so we can modify the
+ * process-wide umask.
+ */
+ umask(create_mode);
+ /*
+ * First try creating shm (or get rw access). We need to start
+ * by this because of the ftruncate vs concurrent map race.
+ * We need to give write access to everyone because of the
+ * ftruncate vs mmap race too. We don't do an exclusive
+ * open, because we allow other processes to
+ * create+ftruncate it concurrently.
+ */
+ wait_shm_fd = shm_open(sock_info->wait_shm_path,
+ O_RDWR | O_CREAT, create_mode);
+ if (wait_shm_fd >= 0) {
+ ret = ftruncate(wait_shm_fd, mmap_size);
+ if (ret) {
+ PERROR("ftruncate");
+ exit(EXIT_FAILURE);
+ }
+ ret = fchmod(wait_shm_fd, read_mode);
+ if (ret) {
+ PERROR("fchmod");
+ exit(EXIT_FAILURE);
+ }
+ exit(EXIT_SUCCESS);
+ }
+ if (errno != EACCES) {
+ ERR("Error opening shm %s", sock_info->wait_shm_path);
+ exit(EXIT_FAILURE);
+ }
+ /*
+ * The shm exists, but we cannot open it RW. It means it
+ * has already been setup and ftruncated, so we can
+ * let the child exit.
+ */
+ exit(EXIT_SUCCESS);
+ } else {
+ return -1;