signal race - Unix

This is a discussion on signal race - Unix ; William Ahern wrote: > Thomas Maier-Komor wrote: > >> Correct. opening a fifo non-blocking returns a valid file descriptor. >> But this file descriptor refers to an empty fifo, if no writer has >> already opened the fifo for writing. ...

+ Reply to Thread
Page 2 of 2 FirstFirst 1 2
Results 21 to 25 of 25

Thread: signal race

  1. Re: signal race

    William Ahern wrote:
    > Thomas Maier-Komor wrote:
    >
    >> Correct. opening a fifo non-blocking returns a valid file descriptor.
    >> But this file descriptor refers to an empty fifo, if no writer has
    >> already opened the fifo for writing. The next call to read will return 0.
    >>
    >> Only after closing the file descriptor and open'ing it after some writer
    >> also has opened the fifo, you get a file descriptor on something that
    >> will return >0 on read.

    >
    > Possibly (I haven't tried). But that doesn't mean select() would also
    > immediately return. And in fact, it doesn't. It won't return readiness
    > _until_ there's something to read, no matter whether the other end is open
    > for writing or not. Indeed, I've just confirmed this behavior on OS X and
    > Linux.
    >
    >> So, using O_NONBLOCK in open, I'd get a loop.

    >
    > Not using pselect(). Don't call read until select() indicates readiness.


    At least on Solaris this is not the case. See the enclosed testcase:

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include

    void *mythread(void *ignored)
    {
    char buf[4096] = "mythread: ";
    int fd, n;
    fd_set readfds, errorfds;
    fd = open("fifo",O_RDONLY);
    n = read(fd,buf+strlen(buf),sizeof(buf)-strlen(buf));
    write(STDOUT_FILENO,buf,strlen(buf));
    close(fd);
    return 0;
    }

    int main(void)
    {
    char buf[4096];
    int fd, n;
    pthread_t thr;
    pthread_attr_t attr;
    fd_set readfds, errorfds;

    fd = open("fifo",O_RDONLY|O_NONBLOCK);
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
    pthread_create(&thr,&attr,mythread,0);
    FD_ZERO(&readfds);
    FD_SET(fd,&readfds);
    FD_ZERO(&errorfds);
    FD_SET(fd,&errorfds);
    pselect(1,&readfds,0,&errorfds,0,0);
    n = read(fd,buf,sizeof(buf));
    write(STDOUT_FILENO,buf,n);
    close(fd);
    return 0;
    }

    thomas@azalin:~/test$ cc -g -mt p.c
    thomas@azalin:~/test$ truss -u libc -u libpthread ./a.out
    execve("a.out", 0xFFBFEBBC, 0xFFBFEBC4) argc = 1
    resolvepath("/usr/lib/ld.so.1", "/lib/ld.so.1", 1023) = 12
    getcwd("/home/thomas/test", 1017) = 0
    resolvepath("/home/thomas/test/a.out", "/home/thomas/test/a.out", 1023) = 23
    stat("/home/thomas/test/a.out", 0xFFBFE998) = 0
    open("/var/ld/ld.config", O_RDONLY) Err#2 ENOENT
    stat("/lib/libthread.so.1", 0xFFBFE450) = 0
    resolvepath("/lib/libthread.so.1", "/lib/libthread.so.1", 1023) = 19
    open("/lib/libthread.so.1", O_RDONLY) = 3
    mmap(0x00010000, 32768, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_ALIGN, 3,
    0) = 0xFF3A0000
    munmap(0xFF3A4000, 16384) = 0
    close(3) = 0
    stat("/lib/libc.so.1", 0xFFBFE450) = 0
    resolvepath("/lib/libc.so.1", "/lib/libc.so.1", 1023) = 14
    open("/lib/libc.so.1", O_RDONLY) = 3
    mmap(0x00010000, 32768, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_ALIGN, 3,
    0) = 0xFF390000
    mmap(0x00010000, 1024000, PROT_NONE,
    MAP_PRIVATE|MAP_NORESERVE|MAP_ANON|MAP_ALIGN, -1, 0) = 0xFF280000
    mmap(0xFF280000, 908061, PROT_READ|PROT_EXEC,
    MAP_PRIVATE|MAP_FIXED|MAP_TEXT, 3, 0) = 0xFF280000
    mmap(0xFF36E000, 35537, PROT_READ|PROT_WRITE|PROT_EXEC,
    MAP_PRIVATE|MAP_FIXED|MAP_INITDATA, 3, 909312) = 0xFF36E000
    mmap(0xFF378000, 1312, PROT_READ|PROT_WRITE|PROT_EXEC,
    MAP_PRIVATE|MAP_FIXED|MAP_ANON, -1, 0) = 0xFF378000
    munmap(0xFF35E000, 65536) = 0
    memcntl(0xFF280000, 144252, MC_ADVISE, MADV_WILLNEED, 0, 0) = 0
    close(3) = 0
    /1: mmap(0x00000000, 8192, PROT_READ|PROT_WRITE|PROT_EXEC,
    MAP_PRIVATE|MAP_ANON, -1, 0) = 0xFF3F0000
    /1: mmap(0x00010000, 24576, PROT_READ|PROT_WRITE|PROT_EXEC,
    MAP_PRIVATE|MAP_ANON|MAP_ALIGN, -1, 0) = 0xFF380000
    /1: munmap(0xFF390000, 32768) = 0
    /1: getcontext(0xFFBFE688)
    /1: getrlimit(RLIMIT_STACK, 0xFFBFE668) = 0
    /1: getpid() = 5567 [5566]
    /1: setustack(0xFF382A88)
    /1@1: -> libc:atexit(0xff3c560c, 0x22000, 0x0, 0x0)
    /1@1: <- libc:atexit() = 0
    /1@1: -> libc:atexit(0x110e0, 0xff3800c0, 0xaca5c, 0x0)
    /1@1: <- libc:atexit() = 0
    /1@1: -> libcpen(0x120f8, 0x80, 0x0, 0x0)
    /1: open("fifo", O_RDONLY|O_NONBLOCK) = 3
    /1@1: <- libcpen() = 3
    /1@1: -> libcthread_attr_init(0xffbfdb44, 0x80, 0x0, 0x0)
    /1: sysconfig(_CONFIG_PAGESIZE) = 8192
    /1@1: <- libcthread_attr_init() = 0
    /1@1: -> libcthread_attr_setdetachstate(0xffbfdb44, 0x40, 0x3a00c, 0x0)
    /1@1: <- libcthread_attr_setdetachstate() = 0
    /1@1: -> libcthread_create(0xffbfdb48, 0xffbfdb44, 0x10d98, 0x0)
    /1: mmap(0x00000000, 65536, PROT_READ|PROT_WRITE,
    MAP_PRIVATE|MAP_ANON, -1, 0) = 0xFF260000
    /1: mmap(0x00000000, 65536, PROT_READ|PROT_WRITE,
    MAP_PRIVATE|MAP_ANON, -1, 0) = 0xFF240000
    /1: sigaction(SIGCANCEL, 0xFFBFD6C0, 0x00000000) = 0
    /1: sysconfig(_CONFIG_STACK_PROT) = 7
    /1: mmap(0x00000000, 1032192, PROT_READ|PROT_WRITE|PROT_EXEC,
    MAP_PRIVATE|MAP_NORESERVE|MAP_ANON, -1, 0) = 0xFF100000
    /1: mmap(0x00010000, 65536, PROT_READ|PROT_WRITE|PROT_EXEC,
    MAP_PRIVATE|MAP_ANON|MAP_ALIGN, -1, 0) = 0xFF220000
    /1: stat("/platform/SUNW,Sun-Blade-2500/lib/libc_psr.so.1",
    0xFFBFD098) = 0
    /1: resolvepath("/platform/SUNW,Sun-Blade-2500/lib/libc_psr.so.1",
    "/platform/sun4u-us3/lib/libc_psr.so.1", 1023) = 37
    /1: open("/platform/SUNW,Sun-Blade-2500/lib/libc_psr.so.1",
    O_RDONLY) = 4
    /1: mmap(0x00010000, 32768, PROT_READ|PROT_EXEC,
    MAP_PRIVATE|MAP_ALIGN, 4, 0) = 0xFF390000
    /1: munmap(0xFF392000, 24576) = 0
    /1@1: -> libc:thr_self(0xff3f0488, 0xff342fa8, 0xff3f4910, 0xff3bea6c)
    /1@1: <- libc:thr_self() = 1
    /1: close(4) = 0
    /1: lwp_create(0xFFBFD7A8, LWP_DETACHED|LWP_SUSPENDED, 0xFFBFD7A4) = 2
    /1: schedctl() = 0xFF20E000
    /1: lwp_continue(2) = 0
    /1@1: <- libcthread_create() = 0
    /1@1: -> libcselect(0x1, 0xffbfdac4, 0x0, 0xffbfda44)
    /2: lwp_create() (returning as new lwp ...) = 0
    /2: setustack(0xFF220288)
    /2: schedctl() = 0xFF20E010
    /2@2: -> libcpen(0x120f0, 0x0, 0x0, 0x0)
    /2: open("fifo", O_RDONLY) (sleeping...)
    /1: pollsys(0xFFBFD9C8, 0, 0x00000000, 0x00000000) (sleeping...)
    /2: open("fifo", O_RDONLY) = 4
    /2@2: <- libcpen() = 4
    /2@2: -> libc:strlen(0xff1faf9c, 0x0, 0x0, 0x0)
    /2@2: <- libc:strlen() = 10
    /2@2: -> libc:strlen(0xff1faf9c, 0x3a200000, 0xff1fafa6, 0x80808080)
    /2@2: <- libc:strlen() = 10
    /2@2: -> libc:read(0x4, 0xff1fafa6, 0xff6, 0x80808080)
    /2: read(4, " 1\n", 4086) = 2
    /2@2: <- libc:read() = 2
    /2@2: -> libc:strlen(0xff1faf9c, 0xff1fafa6, 0x0, 0x0)
    /2@2: <- libc:strlen() = 12
    /2@2: -> libc:write(0x1, 0xff1faf9c, 0xc, 0x80808080)
    mythread: 1
    /2: write(1, " m y t h r e a d : 1\n", 12) = 12
    /2@2: <- libc:write() = 12
    /2@2: -> libc:close(0x4, 0xff1faf9c, 0x0, 0x0)
    /2: close(4) = 0
    /2@2: <- libc:close() = 0
    /2: lwp_sigmask(SIG_SETMASK, 0xFFBFFEFF, 0x0000FFF7) = 0xFFBFFEFF
    [0x0000FFFF]
    /2:
    open("/usr/lib/locale/de_DE.ISO8859-1/LC_MESSAGES/SUNW_OST_SGS.mo",
    O_RDONLY) = 4
    /2: fstat(4, 0xFF1FB918) = 0
    /2: mmap(0x00000000, 145236, PROT_READ, MAP_SHARED, 4, 0) = 0xFF0D0000
    /2: close(4) = 0
    /2: lwp_exit()
    /1: pollsys(0xFFBFD9C8, 0, 0x00000000, 0x00000000) (sleeping...)


    As you can see, pselect sleeps for ever waiting for the first fd to
    become readable. Writing to the fifo causes the detached thread to wake
    up on the blocking open, and successfully read the contents that has be
    written to the fifo. If you remove the thread, main() will block forever
    in pselect.

  2. Re: signal race

    On Aug 12, 4:25 pm, Thomas Maier-Komor
    wrote:
    > William Ahern wrote:

    ....
    > > Not using pselect(). Don't call read until select() indicates
    > > readiness.

    >
    > At least on Solaris this is not the case. See the enclosed testcase:

    ....
    > FD_ZERO(&readfds);
    > FD_SET(fd,&readfds);
    > FD_ZERO(&errorfds);
    > FD_SET(fd,&errorfds);
    > pselect(1,&readfds,0,&errorfds,0,0);


    Please go read the pselect() manpage again. The first argument to
    pselect should be one higher than the highest fd in the fd_sets. In
    this case, you should be passing fd+1. When I make that change, the
    program behaves as desired on a sol10 box.


    Philip Guenther

  3. Re: signal race

    Thomas Maier-Komor wrote:

    > At least on Solaris this is not the case. See the enclosed testcase:


    > fd = open("fifo",O_RDONLY|O_NONBLOCK);
    > pthread_attr_init(&attr);
    > pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
    > pthread_create(&thr,&attr,mythread,0);
    > FD_ZERO(&readfds);
    > FD_SET(fd,&readfds);
    > FD_ZERO(&errorfds);
    > FD_SET(fd,&errorfds);
    > pselect(1,&readfds,0,&errorfds,0,0);


    You have a bug. This should be "pselect(fd + 1, ...)". The first argument
    isn't the number of descriptors in the set, it should be the highest
    numbered descriptor plus 1.


    > As you can see, pselect sleeps for ever waiting for the first fd to
    > become readable. Writing to the fifo causes the detached thread to wake
    > up on the blocking open, and successfully read the contents that has be
    > written to the fifo. If you remove the thread, main() will block forever
    > in pselect.


    It sleeps because of the bug.


  4. Re: signal race

    guenther@gmail.com wrote:
    > On Aug 12, 4:25 pm, Thomas Maier-Komor
    > wrote:
    >> William Ahern wrote:

    > ...
    >>> Not using pselect(). Don't call read until select() indicates
    >>> readiness.

    >> At least on Solaris this is not the case. See the enclosed testcase:

    > ...
    >> FD_ZERO(&readfds);
    >> FD_SET(fd,&readfds);
    >> FD_ZERO(&errorfds);
    >> FD_SET(fd,&errorfds);
    >> pselect(1,&readfds,0,&errorfds,0,0);

    >
    > Please go read the pselect() manpage again. The first argument to
    > pselect should be one higher than the highest fd in the fd_sets. In
    > this case, you should be passing fd+1. When I make that change, the
    > program behaves as desired on a sol10 box.
    >
    >
    > Philip Guenther


    You are right - I missed that point.

    Thanks!

  5. Re: signal race

    William Ahern wrote:
    > Thomas Maier-Komor wrote:
    >
    >> At least on Solaris this is not the case. See the enclosed testcase:

    >
    >> fd = open("fifo",O_RDONLY|O_NONBLOCK);
    >> pthread_attr_init(&attr);
    >> pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
    >> pthread_create(&thr,&attr,mythread,0);
    >> FD_ZERO(&readfds);
    >> FD_SET(fd,&readfds);
    >> FD_ZERO(&errorfds);
    >> FD_SET(fd,&errorfds);
    >> pselect(1,&readfds,0,&errorfds,0,0);

    >
    > You have a bug. This should be "pselect(fd + 1, ...)". The first argument
    > isn't the number of descriptors in the set, it should be the highest
    > numbered descriptor plus 1.
    >
    >
    >> As you can see, pselect sleeps for ever waiting for the first fd to
    >> become readable. Writing to the fifo causes the detached thread to wake
    >> up on the blocking open, and successfully read the contents that has be
    >> written to the fifo. If you remove the thread, main() will block forever
    >> in pselect.

    >
    > It sleeps because of the bug.
    >


    Sorry, I missed that point in the man page.

    Thanks!

+ Reply to Thread
Page 2 of 2 FirstFirst 1 2