1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * semop05 - test for EINTR and EIDRM errors 4 * 5 * Copyright (c) International Business Machines Corp., 2001 6 * 03/2001 - Written by Wayne Boyer 7 * 14/03/2008 Matthieu Fertré (Matthieu.Fertre@irisa.fr) 8 */ 9 10#include <stdio.h> 11#include <stdlib.h> 12#include <sys/types.h> 13#include <sys/wait.h> 14#include "tst_test.h" 15#include "libnewipc.h" 16#include "lapi/sem.h" 17#include "semop.h" 18 19static key_t semkey; 20static int sem_id = -1; 21static struct tst_ts timeout; 22 23struct test_case_t { 24 union semun semunptr; 25 short op; 26 short flg; 27 short num; 28 int error; 29} tc[] = { 30 {{1}, 0, 0, 2, EIDRM}, 31 {{0}, -1, 0, 3, EIDRM}, 32 {{1}, 0, 0, 4, EINTR}, 33 {{0}, -1, 0, 5, EINTR} 34}; 35 36static void do_child(int i) 37{ 38 struct time64_variants *tv = &variants[tst_variant]; 39 struct sembuf s_buf = { 40 .sem_op = tc[i].op, 41 .sem_flg = tc[i].flg, 42 .sem_num = tc[i].num, 43 }; 44 45 TEST(call_semop(tv, sem_id, &s_buf, 1, tst_ts_get(&timeout))); 46 if (TST_RET != -1) { 47 tst_res(TFAIL, "call succeeded when error expected"); 48 exit(0); 49 } 50 51 if (TST_ERR == tc[i].error) 52 tst_res(TPASS | TTERRNO, "expected failure"); 53 else 54 tst_res(TFAIL | TTERRNO, "unexpected failure"); 55 56 exit(0); 57} 58 59static void sighandler(int sig) 60{ 61 if (sig != SIGHUP) 62 tst_brk(TBROK, "unexpected signal %d received", sig); 63} 64 65static void setup(void) 66{ 67 struct time64_variants *tv = &variants[tst_variant]; 68 69 tst_res(TINFO, "Testing variant: %s", tv->desc); 70 semop_supported_by_kernel(tv); 71 72 timeout.type = tv->ts_type; 73 tst_ts_set_sec(&timeout, 2); 74 tst_ts_set_nsec(&timeout, 10000000); 75 76 SAFE_SIGNAL(SIGHUP, sighandler); 77 semkey = GETIPCKEY(); 78 79 sem_id = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA); 80 if (sem_id == -1) 81 tst_brk(TBROK | TERRNO, "couldn't create semaphore in setup"); 82} 83 84static void cleanup(void) 85{ 86 if (sem_id != -1) { 87 if (semctl(sem_id, 0, IPC_RMID) == -1) 88 tst_res(TWARN, "semaphore deletion failed."); 89 } 90} 91 92static void run(unsigned int i) 93{ 94 pid_t pid; 95 96 if (semctl(sem_id, tc[i].num, SETVAL, tc[i].semunptr) == -1) 97 tst_brk(TBROK | TERRNO, "semctl() failed"); 98 99 pid = SAFE_FORK(); 100 101 if (pid == 0) { 102 do_child(i); 103 } else { 104 TST_PROCESS_STATE_WAIT(pid, 'S', 0); 105 106 /* 107 * If we are testing for EIDRM then remove 108 * the semaphore, else send a signal that 109 * must be caught as we are testing for 110 * EINTR. 111 */ 112 if (tc[i].error == EIDRM) { 113 /* remove the semaphore resource */ 114 cleanup(); 115 } else { 116 SAFE_KILL(pid, SIGHUP); 117 } 118 119 waitpid(pid, NULL, 0); 120 } 121 122 if (tc[i].error == EINTR) 123 return; 124 125 sem_id = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA); 126 if (sem_id == -1) 127 tst_brk(TBROK | TERRNO, "couldn't recreate semaphore"); 128} 129 130static struct tst_test test = { 131 .test = run, 132 .tcnt = ARRAY_SIZE(tc), 133 .test_variants = ARRAY_SIZE(variants), 134 .setup = setup, 135 .cleanup = cleanup, 136 .needs_tmpdir = 1, 137 .forks_child = 1, 138}; 139