1/*
2 * Copyright (c) 2002, Intel Corporation. All rights reserved.
3 * Created by:  julie.n.fleischer REMOVE-THIS AT intel DOT com
4 * This file is licensed under the GPL license.  For the full content
5 * of this license, see the COPYING file at the top level of this
6 * source tree.
7 */
8
9/*
10 * Test mq_send() will set errno == EINTR if it is interrupted by a signal.
11 *
12 * Have a child send signals until it starts to block.  At that point, have
13 * the parent send a signal to interrupt the child.  Test passes if errno ==
14 * EINVAL.
15 *
16 * Test very similar to 5-2.c except we don't have the additional test to
17 * verify the child _was_ blocking.
18 */
19
20#include <stdio.h>
21#include <mqueue.h>
22#include <fcntl.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <sys/wait.h>
26#include <unistd.h>
27#include <string.h>
28#include <stdlib.h>
29#include <stdint.h>
30#include <signal.h>
31#include <errno.h>
32#include "posixtest.h"
33
34#define NAMESIZE 50
35#define MSGSTR "0123456789"
36#define BUFFER 40
37#define MAXMSG 5
38
39#define CHILDPASS 1
40#define CHILDFAIL 0
41
42char gqname[NAMESIZE];
43mqd_t gqueue;
44
45/*
46 * This handler is just used to catch the signal and stop sleep (so the
47 * parent knows the child is still busy sending signals).
48 */
49void justreturn_handler(int signo)
50{
51	return;
52}
53
54int main()
55{
56	int pid;
57        const char *msgptr = MSGSTR;
58	struct mq_attr attr;
59	struct sigaction act;
60
61        sprintf(gqname, "/mq_send_12-1_%d", getpid());
62
63	attr.mq_maxmsg = MAXMSG;
64	attr.mq_msgsize = BUFFER;
65        gqueue = mq_open(gqname, O_CREAT |O_RDWR, S_IRUSR | S_IWUSR, &attr);
66        if (gqueue == (mqd_t)-1) {
67                perror("mq_open() did not return success");
68                return PTS_UNRESOLVED;
69        }
70
71	/* parent and child use justreturn_handler to just return out of
72	 * situations -- parent uses to stop it's sleep and wait again for
73	 * the child; child uses to stop its mq_send
74	 */
75	act.sa_handler=justreturn_handler;
76	act.sa_flags=0;
77	sigemptyset(&act.sa_mask);
78	sigaction(SIGABRT, &act, 0);
79
80	if ((pid = fork()) == 0) {
81		/* child here */
82		int i;
83
84		sleep(1);  // give parent time to set up handler
85		for (i=0; i<MAXMSG+1; i++) {
86        		if (mq_send(gqueue, msgptr, strlen(msgptr), 1) == -1) {
87				if (errno == EINTR) {
88				printf("mq_send interrupted by signal\n");
89					return CHILDPASS;
90				} else {
91				printf("mq_send not interrupted by signal\n");
92					return CHILDFAIL;
93				}
94        		}
95			/* send signal to parent each time message is sent */
96			kill(getppid(), SIGABRT);
97		}
98
99		printf("Child never blocked\n");
100		return CHILDFAIL;
101	} else {
102		/* parent here */
103		int j,k;
104
105		for (j=0; j<MAXMSG+1; j++) {
106			if (sleep(3) == 0) {
107			/* If sleep finished, child is probably blocking */
108				kill(pid, SIGABRT); //signal child
109				break;
110			}
111		}
112		mq_close(gqueue);
113		if (mq_unlink(gqname) != 0) {
114			perror("mq_unlink()");
115			return PTS_UNRESOLVED;
116		}
117
118		if (wait(&k) == -1) {
119			perror("Error waiting for child to exit\n");
120			kill(pid, SIGKILL); //kill child if not gone
121			return PTS_UNRESOLVED;
122		}
123		if (!WIFEXITED(k) || !WEXITSTATUS(k)) {
124			printf("Test FAILED\n");
125			return PTS_FAIL;
126		}
127
128		printf("Test PASSED\n");
129		return PTS_PASS;
130	}
131
132	return PTS_UNRESOLVED;
133}
134
135