Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Re: linux perl - interrupted system calls not restarted?

by jakobi (Pilgrim)
on Oct 22, 2009 at 13:29 UTC ( [id://802741]=note: print w/replies, xml ) Need Help??


in reply to linux perl - interrupted system calls not restarted?

consider $SIG{CHLD} = 'IGNORE', which indeed avoids both ending the loop and zombies. Search for reaper and IGNORE.

As you said you need IO::Socket below:

Possibly IO::Socket gets irritated by some %SIG handlers (couldn't find anything on the quick in the source or docs though). 2 possible workarounds I currently see:

  • perlipc: search for sigaction and SA_RESTART then read the section on EINTR directly below
  • IGNORE as handler and place the 'rc' into a file in the child, then in the mainloop regularly waitpid over the children and check for possible rc files from children died with rc!=0. Missing 'rc' and missing child is indicating a more severe error.

Seems a known issue: SOLVED: Re: TCP Client-Server: Server exits though it shouldn't loops forever, and retries accept in case of EINTR. But the loop in the reaper looks like it can stop early; and other syscalls may mess up the detection of EINTR, which seems quite far away from the interrupted syscall.

Maybe just retry accept() upto n times in a row if $client is false.

Note that's there's a small race of the parent running w/o SIG handler, and later children possibly running with it (if it's inheritable by fork; CHECKED: doesn't seem to be inherited)


Please also post your updated code when done, thanx, Peter

  • Comment on Re: linux perl - interrupted system calls not restarted?

Replies are listed 'Best First'.
Re^2: linux perl - interrupted system calls not restarted?
by flipper (Beadle) on Oct 22, 2009 at 14:27 UTC
    Indeed - perldoc perlipc suggests that the info in my camel book is out of date, guess I should update!

    Thanks for your help!
Re^2: linux perl - interrupted system calls not restarted?
by flipper (Beadle) on Oct 22, 2009 at 13:39 UTC
    I need to use SIG{CHLD} in this case - the parent accepts connections, if there is no child running, it starts a child to service the new connection. If there is an existing child, it tells the new client it can't connect as it is in use from ip:port. The child can exit nonzero - when this happens, the parent needs to exit immediately (not at the next accept().

    So the parent needs to detect new connections, and a child exiting. The issue I'm concerned with is more general - If I'm using signals anywhere (eg sleep()), do I need to wrap every system call in a loop to retry it??

      I need to use SIG{CHLD} in this case

      Then you need to check for EINTR

      use Errno qw( EINTR ); for (;;) { my $client = $server->accept(); if (!$client) { next if $! == EINTR; die("Can't accept: $!\n"); } ... }

      If I'm using signals anywhere (eg sleep()), do I need to wrap every system call in a loop to retry it??

      Well, those that are interruptable, yes. That includes sysread. But sysread should already be in a loop since it's not guaranteed to return as many bytes as you requested.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://802741]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (6)
As of 2024-04-18 10:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found