From: Shuanglei Tao Date: Sun, 21 Apr 2019 02:22:37 +0000 (+0800) Subject: protocol: set the pty file descriptor non blocking X-Git-Url: http://git.prime8.dev/?a=commitdiff_plain;h=4cd6d480d646f2dbb6c30dfaa5d9ab8a3ea63de5;p=ttyd.git protocol: set the pty file descriptor non blocking --- diff --git a/src/protocol.c b/src/protocol.c index ca6fe3c..b3f9a33 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -187,56 +187,55 @@ thread_run_command(void *args) { int pty; fd_set des_set; pid_t pid = forkpty(&pty, NULL, NULL, NULL); + if (pid < 0) { /* error */ + lwsl_err("forkpty failed: %d (%s)\n", errno, strerror(errno)); + pthread_exit((void *) 1); + } else if (pid == 0) { /* child */ + setenv("TERM", server->terminal_type, true); + // Don't pass the web socket onto child processes + close(lws_get_socket_fd(client->wsi)); + if (execvp(argv[0], argv) < 0) { + perror("execvp failed\n"); + _exit(-errno); + } + } - switch (pid) { - case -1: /* error */ - lwsl_err("forkpty, error: %d (%s)\n", errno, strerror(errno)); - break; - case 0: /* child */ - if (setenv("TERM", server->terminal_type, true) < 0) { - perror("setenv"); - pthread_exit((void *) 1); - } - // Don't pass the web socket onto child processes - close(lws_get_socket_fd(client->wsi)); - if (execvp(argv[0], argv) < 0) { - perror("execvp"); - pthread_exit((void *) 1); - } - break; - default: /* parent */ - lwsl_notice("started process, pid: %d\n", pid); - client->pid = pid; - client->pty = pty; - client->running = true; - if (client->size.ws_row > 0 && client->size.ws_col > 0) - ioctl(client->pty, TIOCSWINSZ, &client->size); + // set the pty file descriptor non blocking + int status_flags = fcntl(pty, F_GETFL); + if (status_flags != -1) { + fcntl(pty, F_SETFL, status_flags | O_NONBLOCK); + } + lwsl_notice("started process, pid: %d\n", pid); + client->pid = pid; + client->pty = pty; + client->running = true; + if (client->size.ws_row > 0 && client->size.ws_col > 0) + ioctl(client->pty, TIOCSWINSZ, &client->size); + + while (client->running) { + FD_ZERO (&des_set); + FD_SET (pty, &des_set); + struct timeval tv = { 1, 0 }; + int ret = select(pty + 1, &des_set, NULL, NULL, &tv); + if (ret == 0) continue; + if (ret < 0) break; + + if (FD_ISSET (pty, &des_set)) { while (client->running) { - FD_ZERO (&des_set); - FD_SET (pty, &des_set); - struct timeval tv = { 1, 0 }; - int ret = select(pty + 1, &des_set, NULL, NULL, &tv); - if (ret == 0) continue; - if (ret < 0) break; - - if (FD_ISSET (pty, &des_set)) { - while (client->running) { - pthread_mutex_lock(&client->mutex); - while (client->state == STATE_READY) { - pthread_cond_wait(&client->cond, &client->mutex); - } - memset(client->pty_buffer, 0, sizeof(client->pty_buffer)); - client->pty_len = read(pty, client->pty_buffer + LWS_PRE + 1, BUF_SIZE); - client->state = STATE_READY; - pthread_mutex_unlock(&client->mutex); - break; - } + pthread_mutex_lock(&client->mutex); + while (client->state == STATE_READY) { + pthread_cond_wait(&client->cond, &client->mutex); } - - if (client->pty_len <= 0) break; + memset(client->pty_buffer, 0, sizeof(client->pty_buffer)); + client->pty_len = read(pty, client->pty_buffer + LWS_PRE + 1, BUF_SIZE); + client->state = STATE_READY; + pthread_mutex_unlock(&client->mutex); + break; } - break; + } + + if (client->pty_len <= 0) break; } pthread_exit((void *) 0);