]> prime8.dev >> repos - ttyd.git/commitdiff
server: improve signal handling
authorShuanglei Tao <tsl0922@gmail.com>
Sat, 30 Nov 2019 08:44:15 +0000 (16:44 +0800)
committerShuanglei Tao <tsl0922@gmail.com>
Sat, 30 Nov 2019 09:25:53 +0000 (17:25 +0800)
src/protocol.c
src/server.c
src/server.h

index 504aad6333afd37e659b4ca7066e1780c0586913..252fae51e37dd330bf26341242f9f135597ba2d3 100644 (file)
@@ -106,21 +106,9 @@ check_host_origin(struct lws *wsi) {
 }
 
 void
-tty_client_destroy(struct tty_client *client) {
-    if (client->pid <= 0)
-        goto cleanup;
-
-    // kill process (group) and free resource
-    int pgid = getpgid(client->pid);
-    int pid = pgid > 0 ? -pgid : client->pid;
-    if (kill(pid, server->sig_code) != 0) {
-        if (errno == ESRCH)
-            goto cleanup;
-        lwsl_err("kill: %d, errno: %d (%s)\n", pid, errno, strerror(errno));
-    }
-
-cleanup:
+tty_client_free(struct tty_client *client) {
     uv_read_stop((uv_stream_t *) &client->pipe);
+    uv_signal_stop(&client->watcher);
 
     close(client->pty);
 
@@ -164,6 +152,21 @@ read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
     uv_read_stop(stream);
 }
 
+void
+child_cb(uv_signal_t *handle, int signum) {
+    struct tty_client *client;
+    pid_t pid;
+    int status;
+
+    client = (struct tty_client *) handle->data;
+    status = wait_proc(client->pid, &pid);
+    if (pid > 0) {
+        lwsl_notice("process exited with code %d, pid: %d\n", status, pid);
+        client->pid = 0;
+        tty_client_free(client);
+    }
+}
+
 int
 spawn_process(struct tty_client *client) {
     // append url args to arguments
@@ -177,6 +180,8 @@ spawn_process(struct tty_client *client) {
     }
     argv[n] = NULL;
 
+    uv_signal_start(&client->watcher, child_cb, SIGCHLD);
+
     int pty;
     pid_t pid = forkpty(&pty, NULL, NULL, NULL);
     if (pid < 0) { /* error */
@@ -214,6 +219,18 @@ spawn_process(struct tty_client *client) {
     return 0;
 }
 
+void
+kill_process(pid_t pid, int sig) {
+    if (pid <= 0) return;
+
+    // kill process (group) and free resource
+    lwsl_notice("killing process %d with signal %d\n", pid, sig);
+    int pgid = getpgid(pid);
+    if (kill(pgid > 0 ? -pgid : pid, sig) != 0) {
+        lwsl_err("kill: %d, errno: %d (%s)\n", pid, errno, strerror(errno));
+    }
+}
+
 int
 callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
              void *user, void *in, size_t len) {
@@ -250,8 +267,11 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
             client->buffer = NULL;
             client->pty_len = 0;
             client->argc = 0;
+            client->loop = server->loop;
 
-            uv_pipe_init(server->loop, &client->pipe, 0);
+            uv_pipe_init(client->loop, &client->pipe, 0);
+            uv_signal_init(client->loop, &client->watcher);
+            client->watcher.data = client;
 
             if (server->url_arg) {
                 while (lws_hdr_copy_fragment(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_URI_ARGS, n++) > 0) {
@@ -394,7 +414,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
         case LWS_CALLBACK_CLOSED:
             server->client_count--;
             lwsl_notice("WS closed from %s, clients: %d\n", client->address, server->client_count);
-            tty_client_destroy(client);
+            kill_process(client->pid, server->sig_code);
             if (server->once && server->client_count == 0) {
                 lwsl_notice("exiting due to the --once option.\n");
                 force_exit = true;
index fb7d0900dcdf75efbc5f5eefeede44169eceda50..3f9de60ccca7cc2bda218c722f07a9ff43c39673 100644 (file)
@@ -174,8 +174,6 @@ tty_server_free(struct tty_server *ts) {
 void
 signal_cb(uv_signal_t *watcher, int signum) {
     char sig_name[20];
-    pid_t pid;
-    int status;
 
     switch (watcher->signum) {
         case SIGINT:
@@ -183,12 +181,6 @@ signal_cb(uv_signal_t *watcher, int signum) {
             get_sig_name(watcher->signum, sig_name, sizeof(sig_name));
             lwsl_notice("received signal: %s (%d), exiting...\n", sig_name, watcher->signum);
             break;
-        case SIGCHLD:
-            status = wait_proc(-1, &pid);
-            if (pid > 0) {
-                lwsl_notice("process exited with code %d, pid: %d\n", status, pid);
-            }
-            return;
         default:
             signal(SIGABRT, SIG_DFL);
             abort();
@@ -493,7 +485,7 @@ main(int argc, char **argv) {
     }
 
 #if LWS_LIBRARY_VERSION_MAJOR >= 3
-    int sig_nums[] = {SIGINT, SIGTERM, SIGCHLD};
+    int sig_nums[] = {SIGINT, SIGTERM};
     int ns = sizeof(sig_nums)/sizeof(sig_nums[0]);
     uv_signal_t signals[ns];
     for (int i = 0; i < ns; i++) {
index 8a4fde058332c786eb4acf028cd581efc02612eb..1d91ceefcaa0f2f6495ae6cc5a550663c9eab9db 100644 (file)
@@ -34,11 +34,12 @@ struct tty_client {
 
     int pid;
     int pty;
-    int exit_status;
     char *pty_buffer;
     ssize_t pty_len;
 
+    uv_loop_t *loop;
     uv_pipe_t pipe;
+    uv_signal_t watcher;
 };
 
 struct pss_http {