Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

fork and HTTP::Daemon freezes on windows

by patcat88 (Deacon)
on Nov 17, 2010 at 01:20 UTC ( #871885=perlquestion: print w/replies, xml ) Need Help??
patcat88 has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to make a HTTP::Daemon test server that can service 2 clients simultaneously on Windows. Ithreads fork is the easiest thing to use I suppose for a test server. I am using "v5.10.1 built for MSWin32-x86-multi-thread" ActivePerl build 1007. If I comment out the fork and uncomment " #$pid = 0;" (remember the "exit(0);" too) the script works fine, but can service only 1 client at a time. I also tried the forking version of this script on Linux with perl 5.8.8, it worked perfectly. According to Visual Studio debugger, it tells me perl is deadlocked when I break it. The callstack on the child thread is
ntdll.dll!_KiFastSystemCallRet@0() ntdll.dll!_ZwWaitForSingleObject@12() + 0xc ntdll.dll!_RtlpWaitForCriticalSection@4() + 0x8c ntdll.dll!_RtlEnterCriticalSection@4() + 0x46 mswsock.dll!_WSPGetSockName@16() + 0x8e ws2_32.dll!_getsockname@12() + 0x4d > perl510.dll!win32_getsockname(unsigned int s=, sockaddr * addr=, +int * addrlen=) Line 197 + 0x29 C
The callstack on the main perl thread is
ntdll.dll!_KiFastSystemCallRet@0() ntdll.dll!_ZwDeviceIoControlFile@40() + 0xc mswsock.dll!_WSPAccept@24() + 0x1f5 ws2_32.dll!_WSAAccept@20() + 0x85 ws2_32.dll!_accept@12() + 0x17 > perl510.dll!win32_accept(unsigned int s=2382008, sockaddr * addr= +0x00000003, int * addrlen=0x0140f6e4) Line 160 + 0x29 C perl510.dll!Perl_pp_accept(interpreter * my_perl=0x01c75b3c) Lin +e 2588 C perl510.dll!Perl_runops_standard(interpreter * my_perl=0x00243fbc +) Line 38 + 0xc C perl510.dll!S_run_body(interpreter * my_perl=0x00243fbc, long old +scope=1) Line 2432 + 0x7 C perl510.dll!perl_run(interpreter * my_perl=0x00243fbc) Line 2350 + + 0xa C perl510.dll!RunPerl(int argc=2, char * * argv=0x00243f08, char * +* env=0x01242c10) Line 270 + 0x6 C++ perl.exe!main(int argc=2, char * * argv=0x00243f08, char * * env= +0x00242c10) Line 22 + 0x12 C perl.exe!_mainCRTStartup() + 0xe3 kernel32.dll!_BaseProcessStart@4() + 0x23
Callstack in Perl before the freeze is, line 246, in IO::Socket::sockname, line 270, in IO::Socket::sockaddr, line 42, in HTTP::Daemon::url, line 147, in HTTP::Daemon::ClientConn::get_request, line 24, in main
The script is
#!/usr/bin/perl -w use HTTP::Daemon; use warnings; use strict; $HTTP::Daemon::DEBUG =1; my $page = "Hello World!"; my $httpresponsestr = "HTTP/1.1 200 OK\nConnection: close\nDate: Sat, +16 Oct 2010 04:41:51 GMT\nCache-Control: no-store, no-cache, must-rev +alidate\nContent-Length: ".length($page)."\n\n".$page; $| = 1; my $d = HTTP::Daemon->new (LocalPort => 80) || die "server died"; print "Please contact me at: <URL:", $d->url, ">\n"; while (my $c = $d->accept) { my $pid = fork(); #my $pid = 0; if(!defined($pid)) {die "Fork failed."} elsif ($pid == 0) { my $sn; $sn = $c->sockaddr; $sn = $c->sockname; my $r = $c->get_request; print "after get_request r\n"; if ($r->method eq 'GET') { print "is a get\n"; $c->print($httpresponsestr); } else { print "forbidden"; $c->send_error(RC_FORBIDDEN()); } $c->close; print "closed\n"; #comment this out when fork disabled exit(0); } print "fork parent out\n"; }
Whats wrong with my code? Does perl's fork not support sockets?

Replies are listed 'Best First'.
Re: fork and HTTP::Daemon freezes on windows
by BrowserUk (Pope) on Nov 17, 2010 at 06:06 UTC
    Whats wrong with my code?

    Probably nothing on systems that have native fork.

    Does perl's fork not support sockets?

    You are probably aware that fork on windows is emulated using threads. You should also be aware that it is a very poor emulation. The simple answer is don't use it.

    The more complicated answer is: spend hours days and weeks trying to understand where it is falling short, then realise that there is probably nothing you (or anyone?) can do to correct it; and stop using it.

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: fork and HTTP::Daemon freezes on windows (spawn)
by tye (Sage) on Nov 17, 2010 at 16:50 UTC

    Looks like Win32 "get sock name" can't be done by one thread (by which I mean "Win32 thread" not iThread) while another thread is in the middle of "accept" (on a different socket). It doesn't look like it is Perl locks that are causing the deadlock based on Perl's "accept" and "get sock name" being in the middle of calling Win32's "accept" and "get sock name" (respectively).

    So the problem should go away if you replace emulated fork() with spawning, taking care to inherit the parent's file handle in the child. And this method works on Win32 (Apache uses it).

    But in trying to quickly throw together the pieces needed to do this in Perl, I have my doubts that Perl can currently support it well (at least in the case of sockets and even more so when trying to use something like HTTP::Daemon).

    So, rather than inherit a socket created in the parent, you might just spawn and create separate sockets in each process using

    my $d= HTTP::Daemon->new( ... ReuseAddr=>1, ... );

    I'm not certain that such "separate but equal" sockets will work as desired, but it seems worth trying.

    "Spawn" in Win32 Perl can be spelled something like

    system( 1, $^X, $0, @ARGV );

    but probably add something to let the child know it is a child. For example, set some %ENV variable or add some extra argument to the child's command line.

    - tye        

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://871885]
Approved by BrowserUk
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (2)
As of 2018-02-22 07:44 GMT
Find Nodes?
    Voting Booth?
    When it is dark outside I am happiest to see ...

    Results (288 votes). Check out past polls.