in reply to RE: For all your forking needs..
in thread For all your forking needs..

wait most certainly is not deprecated. Please don't make things like this up.

Perl developers have an official way to communicate what is and is not deprecated. That way is to put the deprecation into the documentation, and warnings. Were wait deprecated I would expect to see this fact documented on my machine in perldiag and where-ever else it appears. Which in this case would be perlfaq8, perlfunc, perlipc, perlport, perltoc, perlvar. The only warning is in perlport where it says that wait is not implemented on MacOS and VOS.

For a contrast, compare to $[ which really is deprecated. Looking for $[ in the documentation I find it in perldata (says deprecated), perldiag (says deprecated), perlembed (comment by line that breaks it), perlfaq4 (accidental match), perlport (accidental match), perltoc (part of a long list), and perlvar (says its use is discouraged).

An incidental note, respected books such as the Cookbook use wait liberally. If it is truly deprecated, then that is news to the people who maintain Perl!

All of which is a long way to say that I am one of the -- votes on your node, and I am for a good reason. Because you are giving wrong advice.

  • Comment on RE (tilly) 2: For all your forking needs..

Replies are listed 'Best First'.
RE: (AgentM) RE (tilly) 2: For all your forking needs..
by AgentM (Curate) on Oct 13, 2000 at 05:05 UTC
    According to the lateW. Richard Stevens, arguably the foremost authority on UNIX programming and teaching until his sudden death in 1999, wait() should not be used in any new programming. wait() is an old function dating back to the early days of SysV. The problem with wait() is that it allows zombie processes to come around- and quite easily, may I add. Wait() blocks until a child exits. If you have multiple children, you are supposed to wait() after catching SIGCHLD until all children have been dismissed. But during this loop effect, since most people/ vendors ignore the new POSIX sigqueue() function, UNIX signals are not queued and thus a child can become a zombie while storing the returned result resetting wait(). What's worse is that this problem is nondeterministic, meaning that every time you run the program, you are unlikely to get similar results- this leads, of course, to code that is impossible to debug. The solution cannot be found with some trick with wait()- instead one must default to waitpid(). One must call waitpid() in a loop when you catch the SIGCHLD. Furthermore, waitpid() allows a WNOHANG flag which will allow your program to continue and not block forever if you have no more children. Thus, all children are caught- no zombies. Quoting from his famous "UNIX Network Programming- Vol. I", "...we cannot call wait in a loop, because there is no way to prevent wait from blocking if there exist running children that have not yet terminated." and "Establishing a signal handler and calling wait from that handler is insufficient for preventing zombies...The correct solution is to call waitpid instead of wait." (p. 127) In Perl, this is especially dangerous, since what you may see as one function call, may be actually multiple C functions and even several uninterruptible kernel calls. An interruption (signal catch) there can be especially bad. So the only solution is waitpid(). Thanks for the --, though. Hope this helps.
    AgentM Systems or Nasca Enterprises is not responsible for the comments made by AgentM- anywhere.
      I think either you or Stevens misunderstands something, and it certainly isn't Stevens.

      First of all if you look at Run commands in parallel you will see a use of wait that I would support.

      Now let us get at the misunderstanding. What you are quoting Stevens talking about is handling SIGCHILD signals. He is very much correct that you should not do that with wait. The right way to be careful is with waitpid. And indeed the problem is particularly bad in Perl.

      I agree with all that.

      But that is very different from saying that wait itself should be deprecated. Go back to the example I gave you. You see there that it is used carefully. Signals are not being used to track children, rather you are carefully launching children, keeping track of them, and matching children to reaped processes. So what if you block? The desired behaviour is to block!

      But, you say, we should just use a signal handler, right?

      Wrong.

      Perl's signal handling is not very good. First of all while a signal is being handled, if you get a second one you can dump core. Oops. There are various times in normal operation when a signal can cause you to dump core. Double oops. And Perl's signal handling is based on SysV semantics - not BSD or POSIX.

      So even while I agree with everything that Stevens wrote, it is irrelevant since I don't trust signals in Perl. When you don't trust signals then you have to step back and ask yourself, "Do I really want to block?" And if you do, then wait is probably just fine and dandy. When you are talking about signal handlers, it is not good. But for its little niche it is fine.

      Now if you disagree with anything I just said, saying it here is the wrong thing to do. Instead get the current development version of Perl, download it, go into the documentation, and start submitting patches to p5p.

        That's all fine and dandy, but if you have more than one child, you can lose it in between intermittent calls to wait. Plus, if you use wait, you'll never know WHICH child exited. It will only tell you A child exited. That's not very friendly. For one child, this may be OK, but in most cases, you are dealing with more than one. wait() is NOT OK in any case! waitpid is the ONLY correct way to clean up child processes that are not allowed to become zombies.

        Since Perl (built upon C) is an interpreted language, it will never be good with signals, but the least we can do is to use the better function to clean up the zombies! Using wait instead of waitpid is like using kill instead of sigqueue. Sure, it may work in your certain cases, but in the end, it's simply more beneficial to use the function that

        1. returns more information about the condition of the program
        2. allows more programmer extensibly- queued signals vs. unreliable signals/ blocking perhaps forever on wait at the same time creating a zombie vs. the solution to this exact problem
        In short, i fail to grasp your argument on why anyone should use wait vs. waitpid. if you think it is bad advice to recommend a better function to get more info on the same problem, then that's something I've never heard before. It is my opinion (and that of Stevens) that wait should be replaced in EVERY case with waitpid simply because it will promote better programming practice. The WNOHANG flag bonus is reason enough to replace wait that might block forever if you've lost a zombie! Thanks for the interesting battle of books, but I'll stick with my waitpid.
        AgentM Systems or Nasca Enterprises is not responsible for the comments made by AgentM- anywhere.
          A reply falls below the community's threshold of quality. You may see it by logging in.