in reply to Win32 fork and IO::Socket::INET->accept calls

It seems that accept on a inherited handle is no good.

Works:

use strict; use warnings; $|=1; if (fork() == 0) { print("$$: Child 1.$/"); sleep(3); } elsif (fork() == 0) { print("$$: Child 2.$/"); sleep(3); } else { print("$$: Parent.$/"); sleep(3); } print("$$: oye.$/");

Works:

use strict; use warnings; use IO::Socket::INET; $|=1; if (fork() == 0) { print("$$: Child 1.$/"); my $server = IO::Socket::INET->new( Type => SOCK_STREAM, Proto => 'TCP', LocalPort => 2500, Reuse => 1, Listen => 10 ); $server->accept(); } else { sleep(1); # Make sure accept is reached. if (fork() == 0) { print("$$: Child 2.$/"); sleep(3); } else { print("$$: Parent.$/"); sleep(3); } } print("$$: oye.$/");

Doesn't Work:

use strict; use warnings; use IO::Socket::INET; $|=1; my $server = IO::Socket::INET->new( Type => SOCK_STREAM, Proto => 'TCP', LocalPort => 2500, Reuse => 1, Listen => 10 ); if (fork() == 0) { print("$$: Child 1.$/"); $server->accept(); } else { sleep(1); # Make sure accept is reached. if (fork() == 0) { # <------ Doesn't returns until accept returns. print("$$: Child 2.$/"); sleep(3); } else { print("$$: Parent.$/"); sleep(3); } } print("$$: oye.$/");

Could this be related to the fact that fork doesn't actually fork in Win32? (It just starts a new thread.)

Replies are listed 'Best First'.
Re^2: Win32 fork and IO::Socket::INET->accept calls
by pg (Canon) on Nov 04, 2004 at 04:06 UTC

    I can easily make your code work, just by adding a Timeout to your socket, which you should have any way. A server socket without timeout can run into many problems. Other than the problem you demo'd here, it could also become a dead socket (a socket that cannot be awakened by accept()), if you leave it idle for long enough.

    use strict; use warnings; use IO::Socket::INET; $|=1; my $server = IO::Socket::INET->new( Proto => 'TCP', LocalPort => 2500, Reuse => 1, Listen => 10, Timeout=>1 ); if (fork() == 0) { print("$$: Child 1.$/"); $server->accept(); } else { sleep(1); # Make sure accept is reached. if (fork() == 0) { # <------ Doesn't returns until accept returns. print("$$: Child 2.$/"); sleep(3); } else { print("$$: Parent.$/"); sleep(3); } } print("$$: oye.$/");

      But why would accept in one pseudo-process (thread) tie up a function (fork) in another pseudo-process (thread)? Does any other function have the same effect?

      I'm definitely interested in hearing how "a server socket without timeout can run into many problems". Could you elaborate?

        One problem I ran into many times in the past is that, with this kind of code:

        my $s = IO::Socket::INET->new(Proto => "tcp", LocalAddr => "localhost" +, LocalPort => 3000, Listen => 10); for (my $c = $s->accept()) { ... }

        If you leave it alone for hours and there is no client come to connect, you might never be able to accept() connection any more, even when there is client wants to conenct. I ran into this many times in the past. To resolve this, I simply let the accept() timeout periodically.

        "But why would accept in one pseudo-process (thread) tie up a function (fork) in another pseudo-process (thread)? "

        Don't jump to conclusion that this has anything to do with thread, unless you come up a piece of threading code to demo the same problem.