Re: Bad Network SIGIO on Linux-2.4.19

lists@corewars.org
Wed, 21 Aug 2002 16:24:06 +0200


This is a fix included since 2.4.19-pre5-aa1.

You're assuming that every SIGIO coming your way
1) is coming via fd 0
2) is a POLL_IN interrupt

You should either be polling the file descriptor (0) from the signal
handler, or using SA_SIGINFO (see sigaction(2)) to determine
which interrupt it is.

Regards,
Sapan

On Fri, Aug 16, 2002 at 03:27:33PM -0400, Richard B. Johnson wrote:
>
> This stand-alone program demonstrates the problem previously
> reported.
>
> If you execute this locally, the program will wait for any
> input from the terminal (STDIN_FILENO) and then it will
> terminate. This is the expected behavior.
>
> If you execute this while logged in using telnet, using linux-2.4.18,
> this program will also execute as expected.
>
> However, if you execute using linux-2.4.19, when logged in using
> telnet, the program will exit as soon as the child writes the
> first '.' to the terminal because a SIGIO signal is being incorrectly
> generated for both output and input.
>
>
> #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 <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)
> {
> 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)
> {
> enab = 0;
> }
> 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 */
> for(i=0; i < 0x10; i++)
> {
> (void)sleep(1);
> 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;
> }
>
>
>
> Cheers,
> Dick Johnson
> Penguin : Linux version 2.4.19 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.
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/