I believe, this code is better.
The attached patch should be applied over previously attached
open_init_pty.c source.
Changes:
* BUFSIZE changed to 2KiB (from 16KiB), it seems to me sufficient.
* When no file-descriptor is available to monitor by select(),
waitpid() in blocking mode is called.
* An empty signal handler for SIGCHLD is installed, because ignored
signal (default) does not interrupts I/O calls.
Best Regards
--
Zito
--- open_init_pty.c~v1 2008-04-23 13:13:03.000000000 +0200
+++ open_init_pty.c 2008-04-23 14:52:02.000000000 +0200
@@ -29,6 +29,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <signal.h>
#include <errno.h>
#include <sysexits.h>
@@ -43,7 +44,7 @@
#define MAXRETR 3 /* The max number of IO retries on a fd */
-#define BUFSIZE 16384 /* The ring buffer size */
+#define BUFSIZE 2048 /* The ring buffer size */
static struct termios saved_termios;
static int saved_fd = -1;
@@ -165,13 +166,9 @@
return n;
}
-
-#define FD_SET_VALUE(fd, fdset, value) \
- if (value) \
- FD_SET(fd, fdset); \
- else \
- FD_CLR(fd, fdset);
-
+void sigchld_handler(int asig __attribute__ ((unused)))
+{
+}
int main(int argc, char *argv[])
{
@@ -194,6 +191,12 @@
exit(1);
}
+ /* Wee need I/O calls to fail with EINTR on SIGCHLD... */
+ if ( signal(SIGCHLD, sigchld_handler) == SIG_ERR ) {
+ perror("signal(SIGCHLD,...)");
+ exit(EX_OSERR);
+ }
+
if (isatty(STDIN_FILENO)) {
/* get terminal parameters associated with stdout */
if (tcgetattr(STDOUT_FILENO, &tty_attr) < 0) {
@@ -281,14 +284,41 @@
do {
/* Accept events only on fds, that we can handle now. */
- FD_SET_VALUE(pty_master, &readfds,
- ringbuf_space(&outbuf) > 0 && err_n_rpty < MAXRETR);
- FD_SET_VALUE(pty_master, &writefds,
- ! ringbuf_isempty(&inbuf) && err_n_wpty < MAXRETR);
- FD_SET_VALUE(STDIN_FILENO, &readfds,
- ringbuf_space(&inbuf) > 0 && err_n_stdin < MAXRETR);
- FD_SET_VALUE(STDOUT_FILENO, &writefds,
- ! ringbuf_isempty(&outbuf) && err_n_stdout < MAXRETR);
+ int do_select = 0;
+
+ if ( ringbuf_space(&outbuf) > 0 && err_n_rpty < MAXRETR ) {
+ FD_SET(pty_master, &readfds);
+ do_select = 1;
+ } else
+ FD_CLR(pty_master, &readfds);
+
+ if ( ! ringbuf_isempty(&inbuf) && err_n_wpty < MAXRETR ) {
+ FD_SET(pty_master, &writefds);
+ do_select = 1;
+ } else
+ FD_CLR(pty_master, &writefds);
+
+ if ( ringbuf_space(&inbuf) > 0 && err_n_stdin < MAXRETR ) {
+ FD_SET(STDIN_FILENO, &readfds);
+ do_select = 1;
+ } else
+ FD_CLR(STDIN_FILENO, &readfds);
+
+ if ( ! ringbuf_isempty(&outbuf) && err_n_stdout < MAXRETR ) {
+ FD_SET(STDOUT_FILENO, &writefds);
+ do_select = 1;
+ } else
+ FD_CLR(STDOUT_FILENO, &writefds);
+
+ if ( ! do_select )
+ {
+#ifdef DEBUG
+ fprintf(stderr, "No I/O job for us, calling waitpid()...\n");
+#endif
+ while ( waitpid(child_pid, &child_exit_status, 0) < 0 )
+ ;
+ break;
+ }
int select_rc = select(pty_master + 1,
&readfds, &writefds, &exceptfds, NULL);