This entails reordering the code which reads the answer, to check for
the process exiting before reading its output. This also means that
we deadlock the service if it tries to write more than a pipe-buffer's
worth of stuff, but we're expecting a single character, dammit -- it
shouldn't try to give us an essay.
If the timeout goes off, we report a temporary failure, as with any
other untoward situation.
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <fcntl.h>
+#if defined(TEST) && !defined(DEBUG)
+# define DEBUG
+#endif
#ifdef DEBUG
# define D(x) x
# include <stdio.h>
#ifdef DEBUG
# define D(x) x
# include <stdio.h>
if (!kid) {
close(0); open("/dev/null", O_RDONLY);
dup2(p[1], 1);
if (!kid) {
close(0); open("/dev/null", O_RDONLY);
dup2(p[1], 1);
close(2); open("/dev/null", O_WRONLY);
close(2); open("/dev/null", O_WRONLY);
close(p[0]); close(p[1]);
execl("/usr/bin/userv", "/usr/bin/userv",
close(p[0]); close(p[1]);
execl("/usr/bin/userv", "/usr/bin/userv",
- "-f", "stdin=/dev/null",
+ "-f", "stdin=/dev/null", "-t", "10",
u.s, serv.s,
tail, sender, key, k + 1,
(char *)0);
_exit(127);
}
close(p[1]);
u.s, serv.s,
tail, sender, key, k + 1,
(char *)0);
_exit(127);
}
close(p[1]);
+ if (wait_pid(&wstat, kid) < 0) { close(p[0]); return (-1); }
+ D( fprintf(stderr, "userv exited with status %d\n", wstat); )
+ if (wstat) { close (p[0]); errno = EAGAIN; return (-1); }
+ if (n != 1) { close (p[0]); errno = EAGAIN; return (-1); }
- if (wait_pid(&wstat, kid) < 0) { return (-1); }
- D( fprintf(stderr, "userv exited with status %d\n", wstat); )
- if (n != 1 || wstat) { errno = EAGAIN; return (-1); }
D( fprintf(stderr, "userv answer was `%c'\n", ch); )
} else if (dlen != 1) {
errno = EIO;
D( fprintf(stderr, "userv answer was `%c'\n", ch); )
} else if (dlen != 1) {
errno = EIO;