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);

Reply via email to