xref: /freebsd/lib/libc/tests/stdio/eintr_test.c (revision 72d5dedfa69fa74801d19dd17c49867882d73d97)
1*72d5dedfSKonstantin Belousov /*
2*72d5dedfSKonstantin Belousov  * Initially written by Yar Tikhiy <yar@freebsd.org> in PR 76398.
3*72d5dedfSKonstantin Belousov  * Bug fixes and instrumentation by kib@freebsd.org.
4*72d5dedfSKonstantin Belousov  */
5*72d5dedfSKonstantin Belousov 
6*72d5dedfSKonstantin Belousov #include <sys/types.h>
7*72d5dedfSKonstantin Belousov #include <sys/socket.h>
8*72d5dedfSKonstantin Belousov #include <sys/stat.h>
9*72d5dedfSKonstantin Belousov #include <sys/wait.h>
10*72d5dedfSKonstantin Belousov #include <err.h>
11*72d5dedfSKonstantin Belousov #include <errno.h>
12*72d5dedfSKonstantin Belousov #include <fcntl.h>
13*72d5dedfSKonstantin Belousov #include <md5.h>
14*72d5dedfSKonstantin Belousov #include <signal.h>
15*72d5dedfSKonstantin Belousov #include <stdio.h>
16*72d5dedfSKonstantin Belousov #include <stdlib.h>
17*72d5dedfSKonstantin Belousov #include <string.h>
18*72d5dedfSKonstantin Belousov #include <unistd.h>
19*72d5dedfSKonstantin Belousov 
20*72d5dedfSKonstantin Belousov #include <atf-c.h>
21*72d5dedfSKonstantin Belousov 
22*72d5dedfSKonstantin Belousov #define NDATA	1000
23*72d5dedfSKonstantin Belousov #define	DELAY	2
24*72d5dedfSKonstantin Belousov 
25*72d5dedfSKonstantin Belousov static void
hup(int signo __unused)26*72d5dedfSKonstantin Belousov hup(int signo __unused)
27*72d5dedfSKonstantin Belousov {
28*72d5dedfSKonstantin Belousov }
29*72d5dedfSKonstantin Belousov 
30*72d5dedfSKonstantin Belousov static int ndata, seq;
31*72d5dedfSKonstantin Belousov 
32*72d5dedfSKonstantin Belousov static void
setdata(int n)33*72d5dedfSKonstantin Belousov setdata(int n)
34*72d5dedfSKonstantin Belousov {
35*72d5dedfSKonstantin Belousov 	ndata = n;
36*72d5dedfSKonstantin Belousov 	seq = 0;
37*72d5dedfSKonstantin Belousov }
38*72d5dedfSKonstantin Belousov 
39*72d5dedfSKonstantin Belousov static char *
getdata(void)40*72d5dedfSKonstantin Belousov getdata(void)
41*72d5dedfSKonstantin Belousov {
42*72d5dedfSKonstantin Belousov 	static char databuf[256];
43*72d5dedfSKonstantin Belousov 	static char xeof[] = "#";
44*72d5dedfSKonstantin Belousov 
45*72d5dedfSKonstantin Belousov 	if (seq > ndata)
46*72d5dedfSKonstantin Belousov 		return (NULL);
47*72d5dedfSKonstantin Belousov 	if (seq == ndata) {
48*72d5dedfSKonstantin Belousov 		seq++;
49*72d5dedfSKonstantin Belousov 		return (xeof);
50*72d5dedfSKonstantin Belousov 	}
51*72d5dedfSKonstantin Belousov 	sprintf(databuf, "%08d xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n", seq++);
52*72d5dedfSKonstantin Belousov 	return (databuf);
53*72d5dedfSKonstantin Belousov }
54*72d5dedfSKonstantin Belousov 
55*72d5dedfSKonstantin Belousov ATF_TC_WITHOUT_HEAD(eintr_test);
ATF_TC_BODY(eintr_test,tc)56*72d5dedfSKonstantin Belousov ATF_TC_BODY(eintr_test, tc)
57*72d5dedfSKonstantin Belousov {
58*72d5dedfSKonstantin Belousov 	char c, digest0[33], digest[33], *p;
59*72d5dedfSKonstantin Belousov 	FILE *fp;
60*72d5dedfSKonstantin Belousov 	int i, s[2], total0, total;
61*72d5dedfSKonstantin Belousov 	MD5_CTX md5;
62*72d5dedfSKonstantin Belousov 	pid_t child;
63*72d5dedfSKonstantin Belousov 	struct sigaction sa;
64*72d5dedfSKonstantin Belousov 
65*72d5dedfSKonstantin Belousov 	MD5Init(&md5);
66*72d5dedfSKonstantin Belousov 	setdata(NDATA);
67*72d5dedfSKonstantin Belousov 	for (total0 = 0; (p = getdata()) != NULL; total0 += strlen(p))
68*72d5dedfSKonstantin Belousov 		MD5Update(&md5, p, strlen(p));
69*72d5dedfSKonstantin Belousov 	p = MD5End(&md5, digest0);
70*72d5dedfSKonstantin Belousov 
71*72d5dedfSKonstantin Belousov 	sa.sa_handler = hup;
72*72d5dedfSKonstantin Belousov 	sigemptyset(&sa.sa_mask);
73*72d5dedfSKonstantin Belousov 	sa.sa_flags = 0;
74*72d5dedfSKonstantin Belousov 	ATF_REQUIRE(sigaction(SIGHUP, &sa, NULL) == 0);
75*72d5dedfSKonstantin Belousov 
76*72d5dedfSKonstantin Belousov 	ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, s) == 0);
77*72d5dedfSKonstantin Belousov 
78*72d5dedfSKonstantin Belousov 	switch (child = fork()) {
79*72d5dedfSKonstantin Belousov 	case -1:
80*72d5dedfSKonstantin Belousov 		atf_tc_fail("fork failed %s", strerror(errno));
81*72d5dedfSKonstantin Belousov 		break;
82*72d5dedfSKonstantin Belousov 
83*72d5dedfSKonstantin Belousov 	case 0:
84*72d5dedfSKonstantin Belousov 		ATF_REQUIRE((fp = fdopen(s[0], "w")) != NULL);
85*72d5dedfSKonstantin Belousov 		close(s[1]);
86*72d5dedfSKonstantin Belousov 		setdata(NDATA);
87*72d5dedfSKonstantin Belousov 		while ((p = getdata())) {
88*72d5dedfSKonstantin Belousov 			for (; *p;) {
89*72d5dedfSKonstantin Belousov 				if (fputc(*p, fp) == EOF) {
90*72d5dedfSKonstantin Belousov 					if (errno == EINTR) {
91*72d5dedfSKonstantin Belousov 						clearerr(fp);
92*72d5dedfSKonstantin Belousov 					} else {
93*72d5dedfSKonstantin Belousov 						atf_tc_fail("fputc errno %s",
94*72d5dedfSKonstantin Belousov 						    strerror(errno));
95*72d5dedfSKonstantin Belousov 					}
96*72d5dedfSKonstantin Belousov 				} else {
97*72d5dedfSKonstantin Belousov 					p++;
98*72d5dedfSKonstantin Belousov 				}
99*72d5dedfSKonstantin Belousov 			}
100*72d5dedfSKonstantin Belousov 		}
101*72d5dedfSKonstantin Belousov 		fclose(fp);
102*72d5dedfSKonstantin Belousov 		break;
103*72d5dedfSKonstantin Belousov 
104*72d5dedfSKonstantin Belousov 	default:
105*72d5dedfSKonstantin Belousov 		close(s[0]);
106*72d5dedfSKonstantin Belousov 		ATF_REQUIRE((fp = fdopen(s[1], "r")) != NULL);
107*72d5dedfSKonstantin Belousov 		sleep(DELAY);
108*72d5dedfSKonstantin Belousov 		ATF_REQUIRE(kill(child, SIGHUP) != -1);
109*72d5dedfSKonstantin Belousov 		sleep(DELAY);
110*72d5dedfSKonstantin Belousov 		MD5Init(&md5);
111*72d5dedfSKonstantin Belousov 		for (total = 0;;) {
112*72d5dedfSKonstantin Belousov 			i = fgetc(fp);
113*72d5dedfSKonstantin Belousov 			if (i == EOF) {
114*72d5dedfSKonstantin Belousov 				if (errno == EINTR) {
115*72d5dedfSKonstantin Belousov 					clearerr(fp);
116*72d5dedfSKonstantin Belousov 				} else {
117*72d5dedfSKonstantin Belousov 					atf_tc_fail("fgetc errno %s",
118*72d5dedfSKonstantin Belousov 					    strerror(errno));
119*72d5dedfSKonstantin Belousov 				}
120*72d5dedfSKonstantin Belousov 				continue;
121*72d5dedfSKonstantin Belousov 			}
122*72d5dedfSKonstantin Belousov 			total++;
123*72d5dedfSKonstantin Belousov 			c = i;
124*72d5dedfSKonstantin Belousov 			MD5Update(&md5, &c, 1);
125*72d5dedfSKonstantin Belousov 			if (i == '#')
126*72d5dedfSKonstantin Belousov 				break;
127*72d5dedfSKonstantin Belousov 		}
128*72d5dedfSKonstantin Belousov 		MD5End(&md5, digest);
129*72d5dedfSKonstantin Belousov 		fclose(fp);
130*72d5dedfSKonstantin Belousov 		ATF_REQUIRE_MSG(total == total0,
131*72d5dedfSKonstantin Belousov 		    "Total number of bytes read does not match: %d %d",
132*72d5dedfSKonstantin Belousov 		    total, total0);
133*72d5dedfSKonstantin Belousov 		ATF_REQUIRE_MSG(strcmp(digest, digest0) == 0,
134*72d5dedfSKonstantin Belousov 		    "Digests do not match %s %s", digest, digest0);
135*72d5dedfSKonstantin Belousov 		break;
136*72d5dedfSKonstantin Belousov 	}
137*72d5dedfSKonstantin Belousov }
138*72d5dedfSKonstantin Belousov 
ATF_TP_ADD_TCS(tp)139*72d5dedfSKonstantin Belousov ATF_TP_ADD_TCS(tp)
140*72d5dedfSKonstantin Belousov {
141*72d5dedfSKonstantin Belousov 	ATF_TP_ADD_TC(tp, eintr_test);
142*72d5dedfSKonstantin Belousov 	return (atf_no_error());
143*72d5dedfSKonstantin Belousov }
144