Attention is currently required from: Arne Schwabe.

Hello Arne Schwabe, 

I'd like you to reexamine a change. Please visit

    https://gerrit.openvpn.net/c/openvpn/+/2173?usp=email

to look at the new patch set (#3).


Change subject: tun_afunix: reap the child process on close
......................................................................

tun_afunix: reap the child process on close

close_tun_afunix() sent SIGINT to the child but never waited for it,
leaving a zombie on every restart.

Add openvpn_stop_child() next to openvpn_waitpid_check(). It waits up
to a second for the child to exit, then SIGKILLs it and waits up to
another second. It doesn't wait when SIGINT can't be delivered, e.g. to
a child started before --user dropped privileges.

openvpn_waitpid_check() now returns false and logs why when waitpid()
fails, as documented, instead of reporting a process that isn't our
child as running. A clean exit is no longer logged as an error status.

Change-Id: I0705cff831cbd18686721dffbe5960976e3489da
Signed-off-by: Razvan Cojocaru <[email protected]>
---
M src/openvpn/run_command.c
M src/openvpn/run_command.h
M src/openvpn/tun_afunix.c
3 files changed, 60 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/73/2173/3

diff --git a/src/openvpn/run_command.c b/src/openvpn/run_command.c
index 0e36dad..db25792 100644
--- a/src/openvpn/run_command.c
+++ b/src/openvpn/run_command.c
@@ -115,10 +115,15 @@
     }
     int status;
     pid_t pidret = waitpid(pid, &status, WNOHANG);
-    if (pidret != pid)
+    if (pidret == 0)
     {
         return true;
     }
+    if (pidret != pid)
+    {
+        msg(msglevel | M_ERRNO, "%scannot wait for external program", 
msg_prefix);
+        return false;
+    }

     if (WIFEXITED(status))
     {
@@ -128,6 +133,10 @@
         {
             msg(msglevel, "%scould not execute external program (exit code 
127)", msg_prefix);
         }
+        else if (exitcode == 0)
+        {
+            msg(msglevel, "%sexternal program exited", msg_prefix);
+        }
         else
         {
             msg(msglevel, "%sexternal program exited with error status: %d", 
msg_prefix, exitcode);
@@ -140,6 +149,44 @@

     return false;
 }
+
+/* Returns true if the child was reaped (or is gone) within ms milliseconds. */
+static bool
+wait_for_child_exit(pid_t pid, const char *msg_prefix, unsigned int ms)
+{
+    for (unsigned int waited = 0; openvpn_waitpid_check(pid, msg_prefix, 
D_CLOSE); waited += 10)
+    {
+        if (waited >= ms)
+        {
+            return false;
+        }
+        platform_sleep_milliseconds(10);
+    }
+    return true;
+}
+
+void
+openvpn_stop_child(pid_t pid, const char *msg_prefix)
+{
+    if (kill(pid, SIGINT) != 0)
+    {
+        msg(M_WARN | M_ERRNO, "%scannot stop child process %d", msg_prefix, 
(int)pid);
+        return;
+    }
+
+    if (wait_for_child_exit(pid, msg_prefix, 1000))
+    {
+        return;
+    }
+
+    msg(M_WARN, "%schild process %d did not exit on SIGINT, killing it", 
msg_prefix, (int)pid);
+    kill(pid, SIGKILL);
+
+    if (!wait_for_child_exit(pid, msg_prefix, 1000))
+    {
+        msg(M_WARN, "%scannot reap child process %d", msg_prefix, (int)pid);
+    }
+}
 #endif /* ifndef WIN32 */

 bool
diff --git a/src/openvpn/run_command.h b/src/openvpn/run_command.h
index e11b6a1..c1f1f4c 100644
--- a/src/openvpn/run_command.h
+++ b/src/openvpn/run_command.h
@@ -79,6 +79,17 @@
  */
 bool openvpn_waitpid_check(pid_t pid, const char *msg_prefix, msglvl_t 
msglevel);

+/**
+ * Stops and reaps a process started with \c S_NOWAITPID: sends SIGINT,
+ * then SIGKILL if it hasn't exited after a second, and gives up after
+ * another second. Doesn't wait if SIGINT can't be delivered, e.g. to a
+ * process started before --user dropped privileges.
+ *
+ * @param pid            pid of the process to be stopped
+ * @param msg_prefix     prefix of the messages to be printed
+ */
+void openvpn_stop_child(pid_t pid, const char *msg_prefix);
+
 #endif

 /**
diff --git a/src/openvpn/tun_afunix.c b/src/openvpn/tun_afunix.c
index 79d706a..b4daf9d 100644
--- a/src/openvpn/tun_afunix.c
+++ b/src/openvpn/tun_afunix.c
@@ -138,7 +138,7 @@
      * ourselves by accident */
     if (tt->afunix.childprocess)
     {
-        kill(tt->afunix.childprocess, SIGINT);
+        openvpn_stop_child(tt->afunix.childprocess, "AF_UNIX tun: ");
     }

     free(tt->actual_name);

--
To view, visit https://gerrit.openvpn.net/c/openvpn/+/2173?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.openvpn.net/settings?usp=email

Gerrit-MessageType: newpatchset
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: I0705cff831cbd18686721dffbe5960976e3489da
Gerrit-Change-Number: 2173
Gerrit-PatchSet: 3
Gerrit-Owner: Răzvan Cojocaru <[email protected]>
Gerrit-Reviewer: Arne Schwabe <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>
Gerrit-Attention: Arne Schwabe <[email protected]>
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to