]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
main ipc_activity: misc improvements
authorVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 24 Aug 2017 11:59:01 +0000 (13:59 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 24 Aug 2017 12:19:22 +0000 (14:19 +0200)
Stop IPC after getting an error.  One point is the situation when one
of the forks ends for some reason, which lead to problems.
Another point is pipes getting out of sync.

Smaller changes:
- don't free the handle while it's still half-in-use
- don't fully panic here because of ENOMEM, just stop IPC

Fixes https://gitlab.labs.nic.cz/knot/knot-resolver/issues/150

NEWS
daemon/main.c

diff --git a/NEWS b/NEWS
index 7b577935a96c9edffcb50062ab606f681b7840da..3783aaa26c93c3ca603c96fbb3498b1a3c18dd53 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,10 @@ Incompatible changes
   'hasflag' and 'resolved'.
   You can instead write code like qry.flags.NO_0X20 = true.
 
+Bugfixes
+--------
+- fix exiting one of multiple forks (#150)
+
 Improvements
 ------------
 - policy.suffix: update the aho-corasick code (#200)
index cdf622b20b33af13ebaa053235f6b8726176665c..b35fa3eb375ecf035782729827ecf9ce06875b42 100644 (file)
@@ -189,11 +189,6 @@ static void tty_accept(uv_stream_t *master, int status)
        }
 }
 
-static void ipc_close(uv_handle_t *handle)
-{
-       free(handle);
-}
-
 /* @internal AF_LOCAL reads may still be interrupted, loop it. */
 static bool ipc_readall(int fd, char *dst, size_t len)
 {
@@ -214,7 +209,6 @@ static void ipc_activity(uv_poll_t *handle, int status, int events)
        struct engine *engine = handle->data;
        if (status != 0) {
                kr_log_error("[system] ipc: %s\n", uv_strerror(status));
-               ipc_close((uv_handle_t *)handle);
                return;
        }
        /* Get file descriptor from handle */
@@ -232,9 +226,7 @@ static void ipc_activity(uv_poll_t *handle, int status, int events)
                errno = EINVAL;
        }
        if (!rbuf) {
-               kr_log_error("[system] ipc: %s\n", strerror(errno));
-               engine_stop(engine); /* Panic and stop this fork. */
-               return;
+               goto failure;
        }
        if (!ipc_readall(fd, rbuf, len)) {
                goto failure;
@@ -246,17 +238,22 @@ static void ipc_activity(uv_poll_t *handle, int status, int events)
        if (ret > 0) {
                message = lua_tostring(engine->L, -1);
        }
+       /* Clear the Lua stack */
+       lua_settop(engine->L, 0);
        /* Send response back */
        len = strlen(message);
        if (write(fd, &len, sizeof(len)) != sizeof(len) ||
                write(fd, message, len) != len) {
-               kr_log_error("[system] ipc: %s\n", strerror(errno));
+               goto failure;
        }
-       /* Clear the Lua stack */
-       lua_settop(engine->L, 0);
-       return;
+       return; /* success! */
 failure:
-       kr_log_error("[system] ipc: %s\n", strerror(errno));
+       /* Note that if the piped command got read or written partially,
+        * we would get out of sync and only receive rubbish now.
+        * Therefore we prefer to stop IPC, but we try to continue with all else.
+        */
+       kr_log_error("[system] stopping ipc because of: %s\n", strerror(errno));
+       uv_poll_stop(handle);
 }
 
 static bool ipc_watch(uv_loop_t *loop, struct engine *engine, int fd)