On Thu, Apr 08, 2021 at 10:56:26AM +0200, Claudio Jeker wrote:
> Currently when a pipe to some child is closed the main process errors out
> hard. This is not great since the exit reason is not shown.
> Change this to break out of the poll loop and also restructure the wait
> code to use a loop which checks for both exit and signal status.
> I also switched rsync and proc in the pfds and replaced an abort with an
> errx call.
>
> With this I see which signal killed a process e.g. if I kill -9 rsync:
> ...
> rpki-client: ta/afrinic: loaded from network
> rpki-client: ta/apnic: loaded from network
> rpki-client: ta/lacnic: loaded from network
> rpki-client: poll[1]: hangup
> rpki-client: rsync terminated signal 9
I think you meant to initialize rc = 0 at the top of main. As it is now,
rpki-client will always exit with 1 at 'return rc;' since you dropped
the only place that set rc to 0.
Other than that, this reads ok.
>
> --
> :wq Claudio
>
> Index: main.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
> retrieving revision 1.131
> diff -u -p -r1.131 main.c
> --- main.c 7 Apr 2021 16:06:37 -0000 1.131
> +++ main.c 8 Apr 2021 08:48:46 -0000
> @@ -538,7 +538,7 @@ entity_process(int proc, struct stats *s
> st->gbrs++;
> break;
> default:
> - abort();
> + errx(1, "unknown entity type");
> }
>
> entity_queue--;
> @@ -580,7 +580,6 @@ void
> suicide(int sig __attribute__((unused)))
> {
> killme = 1;
> -
> }
>
> #define NPFD 4
> @@ -589,9 +588,9 @@ int
> main(int argc, char *argv[])
> {
> int rc = 1, c, st, proc, rsync, http, rrdp, ok,
> - fl = SOCK_STREAM | SOCK_CLOEXEC;
> + hangup = 0, fl = SOCK_STREAM | SOCK_CLOEXEC;
> size_t i, id, outsz = 0, talsz = 0;
> - pid_t procpid, rsyncpid, httppid, rrdppid;
> + pid_t pid, procpid, rsyncpid, httppid, rrdppid;
> int fd[2];
> struct pollfd pfd[NPFD];
> struct msgbuf *queues[NPFD];
> @@ -599,7 +598,7 @@ main(int argc, char *argv[])
> char *rsync_prog = "openrsync";
> char *bind_addr = NULL;
> const char *cachedir = NULL, *outputdir = NULL;
> - const char *tals[TALSZ_MAX], *errs;
> + const char *tals[TALSZ_MAX], *errs, *name;
> struct vrp_tree v = RB_INITIALIZER(&v);
> struct rusage ru;
> struct timeval start_time, now_time;
> @@ -871,10 +870,10 @@ main(int argc, char *argv[])
> * parsing process.
> */
>
> - pfd[0].fd = rsync;
> - queues[0] = &rsyncq;
> - pfd[1].fd = proc;
> - queues[1] = &procq;
> + pfd[0].fd = proc;
> + queues[0] = &procq;
> + pfd[1].fd = rsync;
> + queues[1] = &rsyncq;
> pfd[2].fd = http;
> queues[2] = &httpq;
> pfd[3].fd = rrdp;
> @@ -909,8 +908,10 @@ main(int argc, char *argv[])
> for (i = 0; i < NPFD; i++) {
> if (pfd[i].revents & (POLLERR|POLLNVAL))
> errx(1, "poll[%zu]: bad fd", i);
> - if (pfd[i].revents & POLLHUP)
> - errx(1, "poll[%zu]: hangup", i);
> + if (pfd[i].revents & POLLHUP) {
> + warnx("poll[%zu]: hangup", i);
> + hangup = 1;
> + }
> if (pfd[i].revents & POLLOUT) {
> /*
> * XXX work around deadlocks because of
> @@ -929,7 +930,8 @@ main(int argc, char *argv[])
> io_socket_blocking(pfd[i].fd);
> }
> }
> -
> + if (hangup)
> + break;
>
> /*
> * Check the rsync and http process.
> @@ -938,7 +940,7 @@ main(int argc, char *argv[])
> * the parser process.
> */
>
> - if ((pfd[0].revents & POLLIN)) {
> + if ((pfd[1].revents & POLLIN)) {
> io_simple_read(rsync, &id, sizeof(id));
> io_simple_read(rsync, &ok, sizeof(ok));
> rsync_finish(id, ok);
> @@ -1013,7 +1015,7 @@ main(int argc, char *argv[])
> * Dequeue these one by one.
> */
>
> - if ((pfd[1].revents & POLLIN)) {
> + if ((pfd[0].revents & POLLIN)) {
> entity_process(proc, &stats, &v);
> }
> }
> @@ -1024,10 +1026,6 @@ main(int argc, char *argv[])
> errx(1, "excessive runtime (%d seconds), giving up", timeout);
> }
>
> - assert(entity_queue == 0);
> - logx("all files parsed: generating output");
> - rc = 0;
> -
> /*
> * For clean-up, close the input for the parser and rsync
> * process.
> @@ -1039,36 +1037,41 @@ main(int argc, char *argv[])
> close(http);
> close(rrdp);
>
> - if (waitpid(procpid, &st, 0) == -1)
> - err(1, "waitpid");
> - if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
> - warnx("parser process exited abnormally");
> - rc = 1;
> - }
> - if (!noop) {
> - if (waitpid(rsyncpid, &st, 0) == -1)
> - err(1, "waitpid");
> - if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
> - warnx("rsync process exited abnormally");
> - rc = 1;
> + for (;;) {
> + pid = waitpid(WAIT_ANY, &st, 0);
> + if (pid == -1) {
> + if (errno == EINTR)
> + continue;
> + if (errno != ECHILD)
> + err(1, "wait");
> + break;
> }
>
> - if (waitpid(httppid, &st, 0) == -1)
> - err(1, "waitpid");
> - if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
> - warnx("http process exited abnormally");
> - rc = 1;
> - }
> + if (pid == procpid)
> + name = "parser";
> + else if (pid == rsyncpid)
> + name = "rsync";
> + else if (pid == httppid)
> + name = "http";
> + else if (pid == rrdppid)
> + name = "rrdp";
> + else
> + name = "unknown";
>
> - if (rrdpon) {
> - if (waitpid(rrdppid, &st, 0) == -1)
> - err(1, "waitpid");
> - if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
> - warnx("rrdp process exited abnormally");
> - rc = 1;
> - }
> + if (WIFSIGNALED(st)) {
> + warnx("%s terminated signal %d", name, WTERMSIG(st));
> + rc = 1;
> + } else if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
> + warnx("%s process exited abnormally", name);
> + rc = 1;
> }
> }
> +
> + /* processing did not finish because of error */
> + if (entity_queue != 0)
> + return 1;
> +
> + logx("all files parsed: generating output");
>
> repo_cleanup(&fpt);
>
>