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