powerman has asked for the wisdom of the Perl Monks concerning the following question:

I'm try to realize safe async IO using signals. Main idea is simple:
1) I've an array of opened FDs
2) Some signal arrive every 0.01 seconds (probably special chield process will send these signals)
3) Signal handler should interrupt current operation (so it should be unsafe); use epoll() to found FDs ready for I/O operations and read/write these FDs into special buffers
4) Main process from time to time will block this signal and check/modify these read/write buffers, then unblock signal

So, the question is: which read/write functions I should use in this signal handler to be 100% safe? As far as I know read(2) and write(2) are reentrant, but I don't know is perl's sysread() reentrant? If sysread isn't reentrant then I probably should use syscall() (this program shouldn't be portable, it should be as fast as possible and work on linux 2.6).

Replies are listed 'Best First'.
Re: Async IO / signals
by matija (Priest) on Apr 19, 2004 at 13:59 UTC
    I think you are going about this entirely the wrong way. There are two propper ways, that I can see:
    • Rewrite your program to work as an event loop: call select($rbits,$wbits,$ebits,0) to find FDs ready for I/O, and process them
    • Write two threads: One does select($rbits,$wbits,$ebits,00.1) </code>(Note the non-zero timeout), which only makes note of which filehandles are ready for I/O, and leaves the information somewhere for the main process to find.
    If the "process I/O buffer" is an operation with a guaranteed upper time limit, the first option is probably preferable.
      Event loop is of course good thing... when it possible. But it isn't always possible: sometimes I need to do very long calculations inside event loop and this will result in FDs timeout and error.
      Also event loop isn't good idea if "process IO buffer" isn't main task of this program.

      Threads... hmm... not in perl. At least - not current iThreads. They are too slow and use too much memory.

      So I wonna to make safe ASYNC IO without threads using SIGNALS as was described before.
Re: Async IO / signals
by hv (Prior) on Apr 19, 2004 at 16:17 UTC

    As far as I know none of perl's functions are reentrant for signal handlers, because pretty much any perl function can allocate memory, and perl's malloc is not reentrant.

    If you have a system malloc that is reentrant, and you've built perl to use it (configure option -Uusemymalloc if it isn't the default for your system), you may have better luck. But I'm not aware that anyone's done the analysis of what within perl is or isn't safe in that context.

    I would normally look to do async i/o using nonblocking reads and a select() loop, as suggested by matija in his response.

    Hugo

Re: Async IO / signals
by sgifford (Prior) on Apr 19, 2004 at 15:44 UTC

    IIRC, read(2) isn't safe to be called in a signal handler, but I'd have to look at one of Richard Stevens' books to be sure.

    Can you just block signals or set a flag while you're doing the sysread? Or could you implement this as two processes communicating through shared memory?

      read(2) is safe to call in a signal handler, I've checked W. Richard Stevens' Advanced Programming in the Unix Environment for confirmation. Of course, you would need the buffer to be allocated beforehand to use read in a perl signal handler to avoid a malloc.
        Agreed. I just verified that in my copy of APUE.