semget(): Check for [EEXIST] error first.
Although POSIX literally permits failing with [EINVAL] if IPC_CREAT and IPC_EXCL were both passed, the semaphore set already exists and has fewer semaphores than nsems, this does not allow an application to retry safely: if the [EINVAL] is actually because of the semmsl limit, an infinite loop would result. PR: 206927
This commit is contained in:
parent
9ef7a36255
commit
f00fb5457e
@ -867,6 +867,11 @@ sys_semget(struct thread *td, struct semget_args *uap)
|
||||
}
|
||||
if (semid < seminfo.semmni) {
|
||||
DPRINTF(("found public key\n"));
|
||||
if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
|
||||
DPRINTF(("not exclusive\n"));
|
||||
error = EEXIST;
|
||||
goto done2;
|
||||
}
|
||||
if ((error = ipcperm(td, &sema[semid].u.sem_perm,
|
||||
semflg & 0700))) {
|
||||
goto done2;
|
||||
@ -876,11 +881,6 @@ sys_semget(struct thread *td, struct semget_args *uap)
|
||||
error = EINVAL;
|
||||
goto done2;
|
||||
}
|
||||
if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
|
||||
DPRINTF(("not exclusive\n"));
|
||||
error = EEXIST;
|
||||
goto done2;
|
||||
}
|
||||
#ifdef MAC
|
||||
error = mac_sysvsem_check_semget(cred, &sema[semid]);
|
||||
if (error != 0)
|
||||
|
@ -152,6 +152,15 @@ main(int argc, char *argv[])
|
||||
|
||||
print_semid_ds(&s_ds, 0600);
|
||||
|
||||
errno = 0;
|
||||
if (semget(semkey, 1, IPC_CREAT | IPC_EXCL | 0600) != -1 ||
|
||||
errno != EEXIST)
|
||||
err(1, "semget IPC_EXCL 1 did not fail with [EEXIST]");
|
||||
errno = 0;
|
||||
if (semget(semkey, 2, IPC_CREAT | IPC_EXCL | 0600) != -1 ||
|
||||
errno != EEXIST)
|
||||
err(1, "semget IPC_EXCL 2 did not fail with [EEXIST]");
|
||||
|
||||
for (child_count = 0; child_count < 5; child_count++) {
|
||||
switch ((child_pid = fork())) {
|
||||
case -1:
|
||||
|
Loading…
Reference in New Issue
Block a user