in reply to Get the process id, and output of a process, in a threaded environment

but now I would like to be able to kill the process started up from this call programmatically. For this, I need the pid, which the open call so kindly returns. Unfortunately setting the environment variables before hand, causes the open to return the process ID of the shell, and not the actual process.

This problem really has nothing to do with threads. The same problem will manifest itself in a single threaded process. Ie. If you use the shell to invoke the executable, you'll get the pid of the shell not the executable.

The solution is actually quite simple. Don't use the shell.

You are using the shell in order to set up the environment that the executable will inherit. But, if you set the environment of your process to that you want the executable to inherit and then spawn the executable directly -- bypassing the shell -- you achieve your goal.

Ie:

{ local %ENV = %ENV; ## make your additions (deletions, changes) here; $ENV{FOO} = 'BAR'; my $pid = open my $pipe, '-|', '/path/to/the/executable', @args or + die ...; sleep $someTime; kill KILL, $pid; } ## the changes to %ENV are undone once you reach here

That's untested pseudocode.


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
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.
  • Comment on Re: Get the process id, and output of a process, in a threaded environment
  • Download Code

Replies are listed 'Best First'.
Re^2: Get the process id, and output of a process, in a threaded environment
by choroba (Cardinal) on Sep 05, 2013 at 21:14 UTC
    The problem is that on non MSWin systems, external commands are invoked with main thread's ENV, not the local one (as documented in the linked page):
    $ perl -Mthreads -e 'async { local %ENV = %ENV; $ENV{CPU} = "/"; open +my $PIPE, "echo \$CPU |"; print <$PIPE>}->join; $ENV{CPU}="MSWin"; sy +stem "echo \$CPU"' x86_64 MSWin
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re^2: Get the process id, and output of a process, in a threaded environment
by rmahin (Scribe) on Sep 05, 2013 at 21:35 UTC

    Yes, the problem is not caused by threads at all as you said. The only reason I mentioned that aspect, is because setting values for %ENV are not picked up on unix machines unless they are set in the main thread. On windows, your code will work as expected with threads, but unix systems will not pick up those environment changes.

    Was writing up an example of my own, but the monk above me beat me to it. Love the community :)

      Then -- with the caveat that I don't have a non-Windows system to hand to test this -- make the changes in main before you spawn the thread. Eg:

      { my $running : shared = 0; local %ENV = %ENV; $ENV{ FOO } = 'BAR'; async{ my $pid = open ...; $running = 1; ... kill ... }->detach; ## Wait until the kid is spawned before exiting the scope. sleep 1 until $running; } ## And repeat till done.

      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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.

        That would be a way to go about it. Unfortunately however, I am using a thread pool (as you and I have previously decided would be best solution for the application described in this thread, which has undergone a number of improvements but overall structure is the same), so any option of setting the environment before thread creation is out of the question, as it will need to constantly change on a per command basis.

        I'll update my original post to have a more clear description of my script