On Mon, 7 Oct 2002, David S. Miller wrote: > From: "Richard B. Johnson" <root@chaos.analogic.com> > Date: Mon, 7 Oct 2002 08:31:32 -0400 (EDT) > > On Wed, 21 Aug 2002, Richard B. Johnson wrote: > > > > > Attached is a script > > Where is this script? It was not included? > Hmmm. Now included twice ;) If you log-in locally, the program executes as expected. It waits for any keyboard input and then exits. If you log-in over the network, so that a socket is being used, it will print HELP!!!!!!! continuously on the screen because it is continually being signalled that I/O is possible instead of being signaled only when things change. This trouble started with Linux-2.4.19. Linux 2.4.18 and previous versions are clean. cat <<EOF >/tmp/xxx.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h> #include <termios.h> #include <fcntl.h> #include <sys/wait.h> #include <sys/poll.h> #include <errno.h> #include <sys/resource.h> #define ERRORS(s) { \ fprintf(stderr, "Error from line %d, file %s, call %s, (%s)\n", \ __LINE__,__FILE__,(s), strerror(errno)); \ } #define FAIL -1 int enab = 0; int alive = 0; static void set_sig(int sig, sig_t funct, int flags); static void set_sig(int sig, sig_t funct, int flags) { struct sigaction sa; if(sigaction(sig, NULL, &sa) == FAIL) ERRORS("sigaction"); sa.sa_flags = flags; sa.sa_handler = funct; if(sigaction(sig, &sa, NULL) == FAIL) ERRORS("sigaction"); return; } static void iotrap(int unused) { struct pollfd pf; pf.fd = STDIN_FILENO; pf.events = POLLIN; pf.revents = 0; (void)poll(&pf, 1, 0); if(pf.revents & POLLIN) enab = 0; else fprintf(stderr, "HELP!!!!!!!!!!!\n"); } static void reaper(int unused) { alive = 0; while(wait3(&unused, WNOHANG, NULL) > 0) ; } int main(int args, char *argv[]); int main(int args, char *argv[]) { int flags; size_t i; pid_t pid; struct termios term, save; set_sig(SIGCHLD, reaper, SA_INTERRUPT|SA_RESTART); set_sig(SIGIO, iotrap, SA_INTERRUPT|SA_RESTART); alive = 1; switch((pid = fork())) { case 0: /* Child */ (void)sleep(1); for(i=0; i < 0x10; i++) { fprintf(stderr, "."); (void)sleep(1); } exit(EXIT_SUCCESS); default: break; } /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ /* * Save terminal characteristics and then set the terminal for raw * input generating a signal upon any received character. */ if(tcgetattr(STDIN_FILENO, &term) == FAIL) ERRORS("tcgetattr"); save = term; term.c_lflag = ISIG; term.c_iflag = 0; if(tcsetattr(STDIN_FILENO, TCSANOW, &term) == FAIL) ERRORS("tcsetattr"); if((flags = fcntl(STDIN_FILENO, F_GETFL)) == FAIL) ERRORS("fcntl"); flags |= (FNDELAY|FASYNC); if(fcntl(STDIN_FILENO, F_SETFL, flags) == FAIL) ERRORS("fcntl"); if(fcntl(STDIN_FILENO, F_SETOWN, getpid()) == FAIL) ERRORS("fcntl"); /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ fprintf(stderr, "Waiting for input......."); enab = 1; while(enab) { pause(); fprintf(stderr, "Got out of pause\n"); } if(alive) kill(pid, SIGINT); fprintf(stderr, "Exit okay, cleaning up...\n"); /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ /* * Restore the terminal characteristics before we exit. Note, the * terminal is shared. We can't just exit! */ flags &= ~(FNDELAY|FASYNC); if(fcntl(STDIN_FILENO, F_SETFL, flags) == FAIL) ERRORS("fcntl"); if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &save) == FAIL) ERRORS("tcsetattr"); set_sig(SIGIO, SIG_DFL, SA_INTERRUPT); fprintf(stderr, "Done!\n"); return 0; } EOF gcc -Wall -o /tmp/xxx /tmp/xxx.c /tmp/xxx Cheers, Dick Johnson Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips). The US military has given us many words, FUBAR, SNAFU, now ENRON. Yes, top management were graduates of West Point and Annapolis.
cat <<EOF >/tmp/xxx.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h> #include <termios.h> #include <fcntl.h> #include <sys/wait.h> #include <sys/poll.h> #include <errno.h> #include <sys/resource.h> #define ERRORS(s) { \ fprintf(stderr, "Error from line %d, file %s, call %s, (%s)\n", \ __LINE__,__FILE__,(s), strerror(errno)); \ } #define FAIL -1 int enab = 0; int alive = 0; static void set_sig(int sig, sig_t funct, int flags); static void set_sig(int sig, sig_t funct, int flags) { struct sigaction sa; if(sigaction(sig, NULL, &sa) == FAIL) ERRORS("sigaction"); sa.sa_flags = flags; sa.sa_handler = funct; if(sigaction(sig, &sa, NULL) == FAIL) ERRORS("sigaction"); return; } static void iotrap(int unused) { struct pollfd pf; pf.fd = STDIN_FILENO; pf.events = POLLIN; pf.revents = 0; (void)poll(&pf, 1, 0); if(pf.revents & POLLIN) enab = 0; else fprintf(stderr, "HELP!!!!!!!!!!!\n"); } static void reaper(int unused) { alive = 0; while(wait3(&unused, WNOHANG, NULL) > 0) ; } int main(int args, char *argv[]); int main(int args, char *argv[]) { int flags; size_t i; pid_t pid; struct termios term, save; set_sig(SIGCHLD, reaper, SA_INTERRUPT|SA_RESTART); set_sig(SIGIO, iotrap, SA_INTERRUPT|SA_RESTART); alive = 1; switch((pid = fork())) { case 0: /* Child */ (void)sleep(1); for(i=0; i < 0x10; i++) { fprintf(stderr, "."); (void)sleep(1); } exit(EXIT_SUCCESS); default: break; } /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ /* * Save terminal characteristics and then set the terminal for raw * input generating a signal upon any received character. */ if(tcgetattr(STDIN_FILENO, &term) == FAIL) ERRORS("tcgetattr"); save = term; term.c_lflag = ISIG; term.c_iflag = 0; if(tcsetattr(STDIN_FILENO, TCSANOW, &term) == FAIL) ERRORS("tcsetattr"); if((flags = fcntl(STDIN_FILENO, F_GETFL)) == FAIL) ERRORS("fcntl"); flags |= (FNDELAY|FASYNC); if(fcntl(STDIN_FILENO, F_SETFL, flags) == FAIL) ERRORS("fcntl"); if(fcntl(STDIN_FILENO, F_SETOWN, getpid()) == FAIL) ERRORS("fcntl"); /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ fprintf(stderr, "Waiting for input......."); enab = 1; while(enab) { pause(); fprintf(stderr, "Got out of pause\n"); } if(alive) kill(pid, SIGINT); fprintf(stderr, "Exit okay, cleaning up...\n"); /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ /* * Restore the terminal characteristics before we exit. Note, the * terminal is shared. We can't just exit! */ flags &= ~(FNDELAY|FASYNC); if(fcntl(STDIN_FILENO, F_SETFL, flags) == FAIL) ERRORS("fcntl"); if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &save) == FAIL) ERRORS("tcsetattr"); set_sig(SIGIO, SIG_DFL, SA_INTERRUPT); fprintf(stderr, "Done!\n"); return 0; } EOF gcc -Wall -o /tmp/xxx /tmp/xxx.c /tmp/xxx