http://qs321.pair.com?node_id=11120257


in reply to “Bad file descriptor” using Log4Perl and IO::Async

We just ran into this 'bug' as well. I assume the original poster has already moved on with his life, but for posterity, it's a simple difference of how IO::Async and perl handle file descriptors by default: perl choosing to keep them alive and IO::Async opting for more isolation and choosing to close all open filehandles that are not enumerated to keep.

What this means is that there is an additional setup argument in all (or at least all that I know of) IO::Async routines that cause forks that allows you to pass the actions for filehandles you don't want to close. If you have particular files that are the only ones you want to keep open, you can do something fancier, but if all you want is to make the errors go away and go on with your life, the code snippet is pretty simple. If you are going for this brute force approach you'll probably want to try and do this near the initial setup of your logger, or at least before you start creating channels, and try not to have any other files open. Otherwise you're liable to end up performing actions on IO::Async Channels that you probably don't want to mess with. Also, if your forked code ever calls exit, you'll want to follow the advice of perlfork from above and use _exit from posix instead (assuming you are on linux).

# Skip the builtins, they are all kept and it doesn't hurt to have # them but they are already handled. my @fds = grep { $_ > 2 } IO::Async::OS->potentially_open_fds(); # Keep them all open. Parens are to make the parser trust that # map was given a code reference and not a hash reference my @setup = map { ("fd$_" => 'keep', ) } @fds; # ... later ... my $thing = IO::Async::Whatever( code => sub { ... }, setup => \@setup );