in reply to Re^2: Using forks and threads
in thread Using forks and threads

You really should read up on the pthreads libraries for your system, or perform a few experiments, to determine what happens when you fork a multi-threaded process. Personally I favour the latter approach as it generally yields quicker results.

A quick scan around suggests that POSIX/Solaris pthreads libraries map fork(2) to forkl(2) which only clones the calling thread, in which case it *ought* to be safe to use fork and threads in the same process which would greatly simplify what you describe. However, sucking and seeing is the only way to be sure.

If Perl's fork isn't compatible with threads on your system and you need to resort to forking early and running your system calls in a separate process, then I don't see much value in using threads. Using one process to run the user interface, and another to run the background processing would seem to be sufficient. Adding a second thread in the first process would simply complicate things as far as I can see.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^4: Using forks and threads
by ColinHorne (Sexton) on Jul 22, 2006 at 03:05 UTC
    I'd just finished writing threads::system when I read your reply.

    It's good news that fork seems to only clone the current thread, but, like you say, it sounds very system-dependant, and inconsistent.

    May I ask for criticism on the following module? If enough people think it's worthwhile, I'll tweak it a bit, and then upload to CPAN (although, I may change the name to something less dominant first):

    #!/usr/bin/perl package threads::system; require Exporter; @ISA = qw{Exporter}; @EXPORT_OK = qw{system}; use threads::shared; use IO::Handle; use strict; use warnings; pipe my ($crh, $cwh) or die "Could not pipe: $!"; # Command string re +ad/write handles pipe my ($erh, $ewh) or die "Could not pipe: $!"; # Exit status read/ +write handles $cwh->autoflush(1); $ewh->autoflush(1); my $sync : shared; my $child = fork; die "Could not fork: $!" if $child < 0; unless ($child) { # We are the child (daemon) - we handle system() ca +lls for our parent close $erh; close $cwh; while (<$crh>) { # Read commands to exec my $child = fork; die "Could not fork: $!" if $child < 0; unless ($child) { # We are the child - we exec() for our pare +nt exec $_; exit $!; } else { # Parent - communicate our child's failure with our +own parent while (my $pid = waitpid $child, 0) { # Is all this reall +y needed? if ($pid < 0) { die "Error: waitpid: $!" } elsif ($pid == 0) { next } else { print $ewh $?, "\n"; last } # Tell parent! } } } # Decide: is the following a feature or a bug? exit; # Should never happen, unless client does system(undef), or + something } else { # Parent close $ewh; close $crh; } sub system { lock($sync); my $string = shift; # TODO: Accept a full list print $cwh $string, "\n" or die "Could not write: $!"; return <$erh>; } 1
    Example of usage:
    #!/usr/bin/perl use threads::system qw{system}; use strict; use warnings; my $code = system("ls -al /etc"); print "Exited with code: $code\n";
    Output is as expected. Thanks
      t's good news that fork seems to only clone the current thread, but, like you say, it sounds very system-dependant, and inconsistent.

      Well, your module definitely wouldn't work on Win32, and given the problems some other, non-win32 people have using the Expect module, it seems unlikely that your delightfully simple module will be sufficiently robust for widespread portability.

      Given that

      • (as you said in your OP), system in a threads appears to work on your system;
      • that the docs for POSIX/Solaris indicate that it should work on those systems;
      • and it does work on Win32;
      • Up-to-date builds of Linux (post 2.6 kernel?) offer NTPL (Native POSIX Threads Libraries) with much closer POSIX conformance than the older LinuxThreads;

      it seems to me that rather than writing a potentially complex module (see Expect.pm) for this, the right solution would be to verify that it does work correctly on POSIX/Solaris systems and remove the dire warning you quoted in your OP, from perlthrtut.

      It might need to be replaced with a list of systems on which it definitely doesn't work correctly, or maybe just a few limitations on specific systems.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.