mirror of
https://github.com/kdlucas/byte-unixbench.git
synced 2025-03-12 00:00:07 +08:00
context1.c - better end-of-stream, signal handling
Addresses "slave write failed: Broken pipe; aborting" There are two processes that are alternating reading and writing a sequence number of sizeof(unsigned long) size, which is 4 bytes on 32-bit ILP32 ABI and 8 bytes on 64-bit LP64 ABI. The read/write passing of incrementing sequence number occurs in infinite loop until an alarm signals each process. There is a race condition where a signal delivered to one process might close the pipes while the second process was still attempting to read or write from the pipes, and before the second process was interrupted with SIGALRM. This patch fixes the race condition that occurs at the end of the test run, after the first SIGALRM is delivered. This patch does not address the paranoid possibility that read() or write() of 4 or 8 bytes might theoretically be a partial read() or write(), but that is extremely unlikely except in the case of a signal being delivered, and the only signal expected is SIGALRM, and the processing of SIGALRM by report() function does not return. (This patch adds code to ignore SIGPIPE, so SIGALRM is the only expected signal.) github: fixes #1
This commit is contained in:
parent
e0b8c00209
commit
777d66eb15
@ -56,6 +56,7 @@ char *argv[];
|
||||
/* set up alarm call */
|
||||
iter = 0;
|
||||
wake_me(duration, report);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if (pipe(p1) || pipe(p2)) {
|
||||
perror("pipe create failed");
|
||||
@ -66,12 +67,20 @@ char *argv[];
|
||||
/* master, write p1 & read p2 */
|
||||
close(p1[0]); close(p2[1]);
|
||||
while (1) {
|
||||
if (write(p1[1], (char *)&iter, sizeof(iter)) != sizeof(iter)) {
|
||||
if ((errno != 0) && (errno != EINTR))
|
||||
if ((ret = write(p1[1], (char *)&iter, sizeof(iter))) != sizeof(iter)) {
|
||||
if ((ret == -1) && (errno == EPIPE)) {
|
||||
alarm(0);
|
||||
report(); /* does not return */
|
||||
}
|
||||
if ((ret == -1) && (errno != 0) && (errno != EINTR))
|
||||
perror("master write failed");
|
||||
exit(1);
|
||||
}
|
||||
if ((ret = read(p2[0], (char *)&check, sizeof(check))) != sizeof(check)) {
|
||||
if ((ret == 0)) { /* end-of-stream */
|
||||
alarm(0);
|
||||
report(); /* does not return */
|
||||
}
|
||||
if ((ret == -1) && (errno != 0) && (errno != EINTR))
|
||||
perror("master read failed");
|
||||
exit(1);
|
||||
@ -92,6 +101,10 @@ char *argv[];
|
||||
close(p1[1]); close(p2[0]);
|
||||
while (1) {
|
||||
if ((ret = read(p1[0], (char *)&check, sizeof(check))) != sizeof(check)) {
|
||||
if ((ret == 0)) { /* end-of-stream */
|
||||
alarm(0);
|
||||
report(); /* does not return */
|
||||
}
|
||||
if ((ret == -1) && (errno != 0) && (errno != EINTR))
|
||||
perror("slave read failed");
|
||||
exit(1);
|
||||
@ -101,8 +114,12 @@ char *argv[];
|
||||
iter, check);
|
||||
exit(2);
|
||||
}
|
||||
if (write(p2[1], (char *)&iter1, sizeof(iter1)) != sizeof(check)) {
|
||||
if ((errno != 0) && (errno != EINTR))
|
||||
if ((ret = write(p2[1], (char *)&iter1, sizeof(iter1))) != sizeof(check)) {
|
||||
if ((ret == -1) && (errno == EPIPE)) {
|
||||
alarm(0);
|
||||
report(); /* does not return */
|
||||
}
|
||||
if ((ret == -1) && (errno != 0) && (errno != EINTR))
|
||||
perror("slave write failed");
|
||||
exit(1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user