From 86595f65b445fb587489c863e93ad2b2337d7497 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 30 Jul 2017 23:11:38 +0200 Subject: [PATCH] stdin/stdout: Only set nonblock flags for non-tty fds. Although the ->post_select methods of all paraslash executables perform I/O only when select(2) reports that the file descriptor is ready, we set the O_NONBLOCK flag for all monitored fds. This is considered good practice because, in general, it might happen that a subsequent read(2) call blocks even if select(2) indicates that the fd is ready for reading. For example, an fd corresponding to a TCP socket might be flagged as ready for reading if a network packet with incorrect checksum has arrived, but a subsequent read(2) blocks until the packet has been retransmitted. However, stdin and stdout often correspond to a terminal device where the above scenario won't happen. Moreover, for terminals it's essential to reset the O_NONBLOCK flag to the old value on exit because the shell refers to the same file description and thus shares the file status flags, including O_NONBLOCK. Many terminal applications, for example dialog(1), expect stdout to be set to blocking mode and fail in arcane ways if O_NONBLOCK is set. When the stdin and stdout tasks are about to exit, they reset the file status flags back to the original values. However if "para_client stat" is killed with SIGINT, SIGTERM or SIGKILL, or put to sleep with SIGSTOP, the O_NONBLOCK flag remains set because para_client does not handle signals at all. para_recv, para_filter and para_write suffer from the same issue. Adding signal handling to these programs would not help in the SIGSTOP case because this signal can not be caught. This patch modifies stdin.c and stdout.c to no longer set O_NONBLOCK for fd 0 and fd 1 if these fds are associated with a terminal device. This is much easier and should do the job as well. --- stdin.c | 3 ++- stdout.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/stdin.c b/stdin.c index e5c40bcb..7b70690b 100644 --- a/stdin.c +++ b/stdin.c @@ -114,6 +114,7 @@ void stdin_task_register(struct stdin_task *sit, struct sched *s) exit(EXIT_FAILURE); } sit->fd_flags = ret; - sit->must_set_nonblock_flag = (sit->fd_flags & O_NONBLOCK) == 0; + sit->must_set_nonblock_flag = (sit->fd_flags & O_NONBLOCK) == 0 + && !isatty(STDIN_FILENO); sit->task = task_register(&ti, s); } diff --git a/stdout.c b/stdout.c index 29db2b7e..b2666159 100644 --- a/stdout.c +++ b/stdout.c @@ -96,6 +96,7 @@ void stdout_task_register(struct stdout_task *sot, struct sched *s) exit(EXIT_FAILURE); } sot->fd_flags = ret; - sot->must_set_nonblock_flag = (sot->fd_flags & O_NONBLOCK) == 0; + sot->must_set_nonblock_flag = (sot->fd_flags & O_NONBLOCK) == 0 + && !isatty(STDOUT_FILENO); sot->task = task_register(&ti, s); } -- 2.39.2