in reply to Re^5: Multi-threads newbie questions
in thread Multi-threads newbie questions

Thanks again. This indeed works perfectly.
I do have one more question. One of the things my 'process_genome' subroutine has to do is to run a few perl scripts (from JBrowse browser package, if it's of interest).

I did not write those scripts and have no control over them. These scripts require to be run in the "correct" directory (they do stuff in the working directory rather then ask a directory path as an argument). So. my 'process_genome' has to 'chdir' to the genome directory. However, as I learned the current directory is shared by all threads, I was suggested to write the following wrapper:

# forks then changes working directory and executes a command sub chdir_and_system { my ( $dir, @exec_args ) = @_; my $pid = fork; die "couldn't fork: $!" unless defined $pid; unless ($pid) { # this is the child chdir($dir); # open STDOUT, ">/dev/null"; # silence subprocess output # open STDERR, ">/dev/null"; # silence subprocess stderr system(@exec_args) == 0 or die "system @exec_args failed"; } wait; die "child error $?" if ($?); }
then call each of the external scripts using something like this:
sub add_gff_track { my ( $browser_project_dir, $gff_file, $track_label, $key, @optiona +l_args ) = @_; my @args = ( "bin/flatfile-to-json.pl", "--gff=$gff_file", "--tracklabel=$track_label", "--key=$key", @optional_args ); chdir_and_system( $browser_project_dir, @args ); }
I was originally suggested to use 'exec' in the wrapper, but after some reading I thought that perhaps 'system' should be used. I'm not sure. the thing is I need to know that when this wrapper sub ends, the system command also ended (other command might rely on its output). I'm also not sure if all the wrapper logic is OK. Bottom line, my threads terminate abnormally. Perhaps the JBrowse scripts don't return a good value even if they succeed?

How would you go about this?

Replies are listed 'Best First'.
Re^7: Multi-threads newbie questions
by BrowserUk (Patriarch) on Sep 20, 2010 at 15:58 UTC
    How would you go about this?

    I would avoid fork and threads in the same program--but then on my platform I avoid fork at almost all costs.

    On my platform (windows), each thread has it's own current working directory:

    c:\test>perl -Mthreads -le"@t = map{ async( sub{ chdir shift;sleep 3;print`cd`} ,$_) } qw[c:\\ c:\\test c:\\test\\_Inline];$_->join for @t" c:\ c:\test c:\test\_Inline

    But I seem to remember that doesn't hold true for other platforms.

    In any case, I'd simply do:

    system "cd $path && theProg @args";

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I finally went with my $out = capture ([0], "cd $path ; theProg @args");

      the forking gave me so much problems... I have no idea why I started using it.

        Where does capture() come from?