in reply to Re: Mysterious bad file descriptor after fork
in thread Mysterious bad file descriptor after fork

Yippie, after one week, and loud thinking while writing on perl monks I finally found the problem.

In the event_loop a select() iterates over two arrays/IO::Select objects ($rd_handles, $wt_handles).

After server start $rd_handles contains only the "$main_socket" and the parent selects only for that socket. After forking, the sockets are closed (child socket in parent, main_socket in child) BUT the $main_socket remained in $rd_handles of the child process. This caused the EBADF, since there was a closed fdesc in that array. It was always there, I dont understand why one variant worked when the other didn't. Strangely enough, the first step to correct that, $rd_handles->remove($main_socket) didn't work. The $main_socket was still in the array along with valid sockets and I still got EBADF from select().

So I decided to undef $rd_handles/$wt_handles, recreate the two objects and add the child socket there.
That fixed it. Thanks for your input, sometimes I have to think loud and none of my coworkers is suitable for that.

As for the architecture... it is a combination of accept once / select over a set of sockets added to rd_/wt_handles after accept and callback procedures registered for each of these sockets. Now when a message arrives over a socket, the associated procedure is called and the result is send back to the client.

It took me a while to understand the inner workings of Msg.pm (props to Mr. Sriram Srinivasan). The module wasn't designed with a forking solution in mind and in it's original form is not intended for production use (as stated by the author). For a long time I avoided messing with it, but now I had to. Learned a lot while doing so.

Best regards
gnork

cat /dev/world | perl -e "(/(^.*? \?) 42\!/) && (print $1))"
errors->(c)
  • Comment on Re^2: Mysterious bad file descriptor after fork