}
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);
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
}
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 */
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) {
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) {
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;
void
signal_cb(uv_signal_t *watcher, int signum) {
char sig_name[20];
- pid_t pid;
- int status;
switch (watcher->signum) {
case SIGINT:
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();
}
#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++) {