1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) International Business Machines Corp., 2001 4 */ 5 6/* 7 * DESCRIPTION 8 * 1) msgsnd(2) fails and sets errno to EAGAIN if the message can't be 9 * sent due to the msg_qbytes limit for the queue and IPC_NOWAIT is 10 * specified. 11 * 2) msgsnd(2) fails and sets errno to EINTR if msgsnd(2) sleeps on a 12 * full message queue condition and the process catches a signal. 13 */ 14 15#include <errno.h> 16#include <unistd.h> 17#include <sys/types.h> 18#include <sys/ipc.h> 19#include <sys/msg.h> 20 21#include "tst_test.h" 22#include "tst_safe_sysv_ipc.h" 23#include "libnewipc.h" 24 25static key_t msgkey; 26static int queue_id = -1; 27static struct buf { 28 long type; 29 char text[MSGSIZE]; 30} snd_buf = {1, "hello"}; 31 32static struct tcase { 33 int flag; 34 int exp_err; 35 /*1: nobody expected 0: root expected */ 36 int exp_user; 37} tcases[] = { 38 {IPC_NOWAIT, EAGAIN, 0}, 39 {0, EINTR, 1} 40}; 41 42static void verify_msgsnd(struct tcase *tc) 43{ 44 TST_EXP_FAIL(msgsnd(queue_id, &snd_buf, MSGSIZE, tc->flag), tc->exp_err, 45 "msgsnd(%i, %p, %i, %i)", queue_id, &snd_buf, MSGSIZE, tc->flag); 46} 47 48static void sighandler(int sig) 49{ 50 if (sig == SIGHUP) 51 return; 52 else 53 _exit(TBROK); 54} 55 56static void do_test(unsigned int n) 57{ 58 pid_t pid; 59 struct tcase *tc = &tcases[n]; 60 61 if (tc->exp_user == 0) { 62 verify_msgsnd(tc); 63 return; 64 } 65 66 pid = SAFE_FORK(); 67 if (!pid) { 68 SAFE_SIGNAL(SIGHUP, sighandler); 69 verify_msgsnd(tc); 70 _exit(0); 71 } 72 73 TST_PROCESS_STATE_WAIT(pid, 'S', 0); 74 SAFE_KILL(pid, SIGHUP); 75 tst_reap_children(); 76} 77 78static void setup(void) 79{ 80 msgkey = GETIPCKEY(); 81 82 queue_id = SAFE_MSGGET(msgkey, IPC_CREAT | IPC_EXCL | MSG_RW); 83 84 while (msgsnd(queue_id, &snd_buf, MSGSIZE, IPC_NOWAIT) != -1) 85 snd_buf.type += 1; 86} 87 88static void cleanup(void) 89{ 90 if (queue_id != -1) 91 SAFE_MSGCTL(queue_id, IPC_RMID, NULL); 92} 93 94static struct tst_test test = { 95 .needs_tmpdir = 1, 96 .needs_root = 1, 97 .forks_child = 1, 98 .tcnt = ARRAY_SIZE(tcases), 99 .setup = setup, 100 .cleanup = cleanup, 101 .test = do_test 102}; 103