Re: Bad Network SIGIO on Linux-2.4.19

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux