in reply to Ulimit makes program hang

This looks like a bug in Perl. It would be nice if people with similar systems and perls could validate or refute your results so we can narrow down where this problem occurs (use a much smaller -u to make it easy reproduce). Perl should report a failure to fork(), not hang.

- tye        

Replies are listed 'Best First'.
Re^2: Ulimit makes program hang (bug)
by JavaFan (Canon) on Aug 13, 2008 at 20:07 UTC
    I don't think it's a bug. The fork() doesn't fail - the fork() is blocked. (Or rather, fork(1) fails, setting errno to EAGAIN).

    You can easily test it. Copy the program, so you have foo calling itself and bar calling itself. Now do from on shell:

    (ulimit -u 50 ./foo)
    This will print a bunch of pids, and the program "hangs". Now from another shell do:
    (ulimit -u 60 ./bar)
    This will print 10 or less pids, and it hangs. Go back to the first window, kill the program, and issue a killall foo (or whatever is the equivalent on your system). Watch the output of the bars.

    When reaching the maximum amount of processes set by ulimit, fork() blocks till another slot becomes available.

      So it isn't a bug in Perl but a change in behavior based on operating system (or some other environmental detail)? My prior experience shows fork failing due to ulimit and other examples in the thread show this behavior as well. Thanks for the insight.

      - tye        

        I don't think it's on the system level, but it's perl that retries. I don't know exactly which functions Perl executes on backticks, but it's probably going to open some pipe. And here's a snippet from the function Perl_my_popen in util.c:
        while ((pid = PerlProc_fork()) < 0) { if (errno != EAGAIN) { PerlLIO_close(p[This]); PerlLIO_close(p[that]); if (did_pipes) { PerlLIO_close(pp[0]); PerlLIO_close(pp[1]); } if (!doexec) Perl_croak(aTHX_ "Can't fork"); return NULL; } sleep(5); }
        As you can see, if the fork fails with an EAGAIN, perl sleeps for 5 seconds and tries again.

        A similar loop is found in Perl_my_popen_list in the same file.

Re^2: Ulimit makes program hang (bug)
by alexm (Chaplain) on Aug 13, 2008 at 18:07 UTC

    It would seem so. I run the script under strace and found that the qx op doesn't use fork syscall on my perl (Ubuntu Hardy), but clone syscall:

    • A working qx...
      21696 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETT +ID|SIGCHLD, child_tidptr=0x7f6015248770) = 21697 21697 close(5) = 0 21697 fcntl(6, F_SETFD, FD_CLOEXEC) = 0 21697 dup2(4, 1) = 1 21697 close(4) = 0 21697 close(3) = 0 21697 rt_sigaction(SIGFPE, {SIG_DFL}, {SIG_IGN}, 8) = 0 21697 execve("./my_program", ["./my_program"], [/* 11 vars */] <unfini +shed ...>
    • A non-working one...
      21742 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETT +ID|SIGCHLD, child_tidptr=0x7f4143c25770) = -1 EAGAIN (Resource tempor +arily unavailable) 21742 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 21742 rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0 21742 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 21742 nanosleep({5, 0}, <unfinished ...>

    The problem is that the nanosleep syscall should not be happening.