Re: `pg_ctl init` crashes when run concurrently; semget(2) suspected - Mailing list pgsql-hackers
From | Tom Lane |
---|---|
Subject | Re: `pg_ctl init` crashes when run concurrently; semget(2) suspected |
Date | |
Msg-id | 2685565.1754862843@sss.pgh.pa.us Whole thread Raw |
In response to | Re: `pg_ctl init` crashes when run concurrently; semget(2) suspected (Tom Lane <tgl@sss.pgh.pa.us>) |
Responses |
Re: `pg_ctl init` crashes when run concurrently; semget(2) suspected
|
List | pgsql-hackers |
I wrote: > This is from current macOS, but equivalent text appears on Linux and > in the POSIX spec. So it's just luck that nobody has reported the > same problem elsewhere --- unless maybe there is some macOS-specific > behavior making it more likely that different installs would try the > same key. Hmm, no, there is a platform dependency here. I made the attached test program to see what happens when there's a key collision, and on Linux I get semget(SEMAS_PER_SET) failed: File exists semget(SEMAS_PER_SET + 1) failed: File exists but macOS and NetBSD give semget(SEMAS_PER_SET) failed: File exists semget(SEMAS_PER_SET + 1) failed: Invalid argument I didn't try other BSDen; this might be a NetBSD-ism that Apple inherited, or maybe it's common among the BSDen. I don't see any text in POSIX specifying which errno is to be returned in this case, so we can't really argue that the behavior is wrong. regards, tom lane #include <stdio.h> #include <errno.h> #include <signal.h> #include <string.h> #include <unistd.h> #include <sys/file.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/stat.h> typedef key_t IpcSemaphoreKey; /* semaphore key passed to semget(2) */ #ifndef HAVE_UNION_SEMUN union semun { int val; struct semid_ds *buf; unsigned short *array; }; #endif #define SEMAS_PER_SET 16 #define IPCProtection (0600) /* access/modify by user only */ int main(int argc, char **argv) { IpcSemaphoreKey semKey = 42; int semId; int semId2; union semun semun; /* * Find a free semaphore key, and create a set with SEMAS_PER_SET semas. */ for(;;) { semId = semget(semKey, SEMAS_PER_SET, IPC_CREAT | IPC_EXCL | IPCProtection); if (semId >= 0) break; semKey++; } /* * Check behavior if we try to make another set with same # of semas. */ semId2 = semget(semKey, SEMAS_PER_SET, IPC_CREAT | IPC_EXCL | IPCProtection); if (semId2 < 0) fprintf(stderr, "semget(SEMAS_PER_SET) failed: %s\n", strerror(errno)); else fprintf(stderr, "semget(SEMAS_PER_SET) unexpectedly succeeded\n"); /* * Check behavior if we try to make another set with more semas. */ semId2 = semget(semKey, SEMAS_PER_SET + 1, IPC_CREAT | IPC_EXCL | IPCProtection); if (semId2 < 0) fprintf(stderr, "semget(SEMAS_PER_SET + 1) failed: %s\n", strerror(errno)); else fprintf(stderr, "semget(SEMAS_PER_SET + 1) unexpectedly succeeded\n"); /* * Clean up */ semun.val = 0; /* unused, but keep compiler quiet */ if (semctl(semId, 0, IPC_RMID, semun) < 0) fprintf(stderr, "semctl(%d, 0, IPC_RMID, ...) failed: %s\n", semId, strerror(errno)); return 0; }
pgsql-hackers by date: