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

close_on_exec in Perl : close socket opened in parent process when fork child , is not working

by chinaxing (Acolyte)
on Jan 17, 2013 at 10:09 UTC ( [id://1013743]=perlquestion: print w/replies, xml ) Need Help??

chinaxing has asked for the wisdom of the Perl Monks concerning the following question:

I open a socket in my main perl program,

than i execute a shell script :'/home/admin/t.sh',

when i use CTRL-C to interrupt the perl program,

i saw that the port '4444' was already openning by the shell script's program。

so,how to close the socket fd when the `system` function was executed ?

the $^F variable is unuseful.

very thanks !
1 #!/bin/env perl 2 use Linux::Inotify2; 3 use Modern::Perl; 4 use Mojo::IOLoop; 5 6 $^F=0; 7 Mojo::IOLoop->server({ 8 port => 4444, 9 },sub{ 10 my ($stream,$chunk) = @_; 11 $stream->write('HTTP/1.1 200 OK'); 12 print " I am server \n"; 13 }); 14 15 system('/home/admin/t.sh &>/dev/null &'); 16
  • Comment on close_on_exec in Perl : close socket opened in parent process when fork child , is not working
  • Download Code

Replies are listed 'Best First'.
Re: close_on_exec in Perl : close socket opened in parent process when fork child , is not working
by eyepopslikeamosquito (Archbishop) on Jan 17, 2013 at 11:18 UTC

    I'm confident that the basic close-on-exec mechanism of $^F works on all Unix platforms because I remember writing a test for it, t/run/cloexec.t, which should be run when Perl is built. Did you build Perl from source and, if so, did the cloexec.t test pass? Which Perl version are you using and which OS? Are you able to run the cloexec.t test on your Perl?

    In any case, even if you didn't explicitly set $^F, I expect the socket fd would be greater than two and so should be closed across an exec for the default value of $^F (see perlvar for details on $^F close-on-exec behaviour).

    BTW, you can see how close-on-exec is implemented by searching for close-on-exec in the Perl C sources, for example from pp_sys.c:

    #if defined(HAS_FCNTL) && defined(F_SETFD) fcntl(fd, F_SETFD, fd > PL_maxsysfd); /* ensure close-on-exe +c */ #endif
    How well this works on all Unices and in all environments, I cannot be certain of. For example, Linux open call cautions:
    Additionally, use of this flag is essential in some multithreaded programs since using a separate fcntl(2) F_SETFD operation to set the FD_CLOEXEC flag does not suffice to avoid race conditions where one thread opens a file descriptor at the same time as another thread does a fork(2) plus execve(2).

    Moreover, calling close on a socket closes your program's interface to the socket not the socket itself. It is up to the kernel to close the socket and it may be kept alive for a few minutes after you close it (see unix socket faq).

    It is going to be tricky to figure out what is going on. A tool like lsof would be especially useful. Perhaps strace too. Along with a very small test program to investigate what is going on.

    Update: as a workaround, instead of calling system, you could try calling fork, then explicitly close the socket, then call exec.

      this should be the mojolicious's problem. normal socket program is ok .

      foreaxmple, the following code, close_on_exec works.
      #!/bin/env perl use Modern::Perl; use IO::Socket; # or Socket; $^F=2; # server my $server_port = 4444; my $server = IO::Socket::INET->new( LocalPort => $server_port, Type => SOCK_STREAM, Reuse => 1, Listen => 10) or die "Couldn't be a tcp server on port $server_port:$!\n"; my $client; while($client = $server->accept()){ say 'client connected ...'; system('/home/admin/t.sh &>/dev/null &'); }
Re: close_on_exec in Perl : close socket opened in parent process when fork child , is not working (explain?)
by tye (Sage) on Jan 17, 2013 at 19:58 UTC

    I'm not sure exactly what you are expecting and how it is not working to your satisfaction. I suspect it is possible to figure that out from what you've provided, but I am finding it rather difficult so I suspect that making that easier may lead to more helpful responses.

    For example, what does "i saw that the port '4444' was already openning by the shell script's program" mean? Is this based on running something like "netstat"? Perhaps if you show the command you ran and the part of the output that you noticed, then it will make your problem easier to understand.

    close-on-exec only closes the instance of the FD in the child. It doesn't do anything to the FD that is open in the parent process. Perhaps you want exec instead of system?

    - tye        

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (3)
As of 2024-04-24 02:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found