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

Discussion in 'Perl Misc' started by 陈云星, Jan 17, 2013.

  1. 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 bythe 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
    17 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
    陈云星, Jan 17, 2013
    #1
    1. Advertising

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

    Ben Morrow <> writes:
    > Quoth =?UTF-8?B?6ZmI5LqR5pif?= <>:


    [...]

    >> 1 #!/bin/env perl
    >> 2 use Linux::Inotify2;
    >> 3 use Modern::perl;
    >> 4 use Mojo::IOLoop;
    >> 5
    >> 6 $^F=0;

    >
    > Don't do that. If you should manage to end up with fds less than 2 with
    > the close-on-exec bit set, you will probably confuse any process you
    > exec.


    That's sort of an understatement: The way UNIX(*) 'file descriptor
    creating' calls work is that a newly created file descriptor will
    always use the lowest available file descriptor number. This means
    that if file descriptor 2 ('stderr') is closed, the next file
    descriptor created by a program running in this environment (assuming
    0 and 1 are still open) will have the number 2 and anything which
    writes 'to the standard error output' in the program will henceforth
    use this file descriptor. It is very likely that the code of the
    program wasn't written with this possibility in mind and that the
    'thing' which is now referred to by the former stderr descriptor is
    actually supposed to be used for something completely different, eg, a
    TCP connection to some remote server who doesn't expect random
    diagnostic output but communication conforming to some kind of
    application protocol.
    Rainer Weikusat, Jan 17, 2013
    #2
    1. Advertising

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

    Ben Morrow <> writes:
    > Quoth =?UTF-8?B?6ZmI5LqR5pif?= <>:
    >> 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 programB
    >>
    >> soChow to close the socket fd when the `system` function was executed ?

    >
    > Well, normally the answer would be 'set the close-on-exec flag', but it
    > is usually set by default on newly-opened filehandles since $^F is
    > usually 2. That means Mojo::IOLoop is going out of its way to clear the
    > flag, which suggests perhaps you should leave it that way.


    Should this be the case, this 'suggests' that 'MoJo' is seriously
    broken in this respect: A listening file descriptor which 'leaks'
    through to an independent program in this way will prevent the actual
    server from being restarted until this independent program has
    terminated because the bind call in the server will fail with
    EADDRINUSE for as long as it is still 'sitting' on this socket. That's
    the kind of errors which makes people reboot 24x7 'server computers' in
    despair because 'some important program' can't be started and no one
    understands why (even if someone understands why, 'go hunting for the
    leaked descriptor to terminate the offending process' may be seriously
    onerous in a sufficiently hostile environment[*]).

    [*] A 'sufficiently hostile environment' I remember would be the
    'NS-BSD' BSD-based NetASQ firewall OS where this problem would
    occasionally prevent restarting the process which provided 'the
    GUI'. I ended up with writing a Perl script which correlated the fstat
    and netstat output together (IIRC), based on the kernel addresses of
    'tcp socket control blocks', this being the only way to determine
    which process had a particular fd open in that environment. And I
    wasn't really one of the support people supposed to deal with these
    beasts, the problem only reached me because this device couldn't be
    rebooted and everybody else was at his wits end (which is completely
    ok for a non-programmer confronted with *this*).
    Rainer Weikusat, Jan 17, 2013
    #3
  4. 陈云星

    C.DeRykus Guest

    Re: close_on_exec in Perl : close socket opened in parent processwhen fork child , is not working

    On Thursday, January 17, 2013 2:03:17 AM UTC-8, 陈云星wrote:
    > 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
    >
    > 17 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;



    Other options would definitely be preferable but if
    you need to close only this particular descriptor
    you could close it in the shell, eg,

    my $fd = fileno($some_socket_stream);
    system("exec $fd <&-; /home/admin/t.sh ....");

    --
    Charles DeRykus
    C.DeRykus, Jan 17, 2013
    #4
  5. Re: close_on_exec in Perl : close socket opened in parent process when fork child , is not working

    Ben Morrow <> writes:
    > Quoth Rainer Weikusat <>:
    >> Ben Morrow <> writes:


    [...]

    >> > Well, normally the answer would be 'set the close-on-exec flag', but it
    >> > is usually set by default on newly-opened filehandles since $^F is
    >> > usually 2. That means Mojo::IOLoop is going out of its way to clear the
    >> > flag, which suggests perhaps you should leave it that way.

    >>
    >> Should this be the case, this 'suggests' that 'MoJo' is seriously
    >> broken in this respect: A listening file descriptor which 'leaks'
    >> through to an independent program in this way will prevent the actual
    >> server from being restarted until this independent program has
    >> terminated because the bind call in the server will fail with
    >> EADDRINUSE for as long as it is still 'sitting' on this socket.

    >
    > I wouldn't call it 'broken'. It is no longer usual for Perl programs of
    > the sort which use frameworks like Mojo to exec external programs, so
    > the question of random programs inheriting your fds shouldn't normally
    > arise.


    Is this documented? If so, it's a misfeature. If not, it's another
    case of "it works on my laptop !!1" (and - surely - no one would ever
    think of doing anything I NEVER do !!2), IOW, it's broken and the
    people who wrote the perl code knew better.

    > It looks as though Mojo clears the CLOEXEC bit because under some
    > circumstance your program will run as a long-running daemon, and it
    > periodically re-execs itself to start from a clean slate.


    If this is the case, it looks suspiciously like "the Mojo code
    contains serious bugs the developers neither understand nor care about
    and they thought periodically invoking exec would be a great
    workaround even if this means that 'exec without preautions' will be
    broken for everyone else despite the perl documentation claims that
    perl deals with this without application programmers having to worry
    about that". In particular, this suggests that 'Mojo' leaks memory.
    Rainer Weikusat, Jan 18, 2013
    #5
  6. Re: close_on_exec in Perl : close socket opened in parent processwhen fork child , is not working

    You are right, I use following code , watch /proc/2312/fd , find that shellscript does not hold any socket fd.

    this should be the mojolicious's problem.

    $cat t.pl
    #!/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 &');

    }



    在 2013å¹´1月17日星期四UTC+8下åˆ7æ—¶14分32秒,Ben Morrow写é“:
    > Quoth =?UTF-8?B?6ZmI5LqR5pif?= <>:
    >
    > > 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 ?

    >
    >
    >
    > Well, normally the answer would be 'set the close-on-exec flag', but it
    >
    > is usually set by default on newly-opened filehandles since $^F is
    >
    > usually 2. That means Mojo::IOLoop is going out of its way to clear the
    >
    > flag, which suggests perhaps you should leave it that way.
    >
    >
    >
    > So, you have two options: clear the flag (with fcntl) just before the
    >
    > system and restore its previous value afterwards, or do the fork and
    >
    > exec manually. In the latter case you can obviously close any
    >
    > filehandles you like between fork and exec.
    >
    >
    >
    > > 1 #!/bin/env perl

    >
    > > 2 use Linux::Inotify2;

    >
    > > 3 use Modern::perl;

    >
    > > 4 use Mojo::IOLoop;

    >
    > > 5

    >
    > > 6 $^F=0;

    >
    >
    >
    > Don't do that. If you should manage to end up with fds less than 2 with
    >
    > the close-on-exec bit set, you will probably confuse any process you
    >
    > exec. Unless you're doing something peculiar, fds 0, 1 and 2 are always
    >
    > open, so there's no need to set $^F lower than 2.
    >
    >
    >
    > In any case, you should localise any global if you change it, and you
    >
    > should be rather careful about calling external code (like Mojo) with
    >
    > important globals set to non-standard values.
    >
    >
    >
    > > 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 &');

    >
    >
    >
    > Careful with that syntax. &> is a cshism, and /bin/sh doesn't
    >
    > necessarily understand it.
    >
    >
    >
    > > 16

    >
    > > 17 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

    >
    >
    >
    > Ben
    陈云星, Jan 18, 2013
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Denon
    Replies:
    1
    Views:
    565
    Saravana [MVP]
    Nov 14, 2003
  2. Chris Torek
    Replies:
    0
    Views:
    623
    Chris Torek
    May 30, 2011
  3. Iñaki Baz Castillo
    Replies:
    7
    Views:
    825
    Iñaki Baz Castillo
    Jan 12, 2010
  4. Noel Dolan
    Replies:
    0
    Views:
    218
    Noel Dolan
    Jul 18, 2004
  5. Bitswapper
    Replies:
    5
    Views:
    120
    Prasad, Ramit
    Aug 27, 2013
Loading...

Share This Page