Skip to content

[2.2] [Process] Add getPid and sendSignal methods to Process #5391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

romainneutron
Copy link
Contributor

Bug fix: no
Feature addition: yes
Backwards compatibility break: no
Symfony2 tests pass: yes
License of the code: MIT

This method is particularly nice for sending posix signal to a process

example of use :

// send a SIGCONT signal to the related process
posix_kill($process->getPid(), SIGCONT);

I've not implement the signal sender in the Process API because it requires posix environment, but I think could be nice to have it and throw an exception in case it's not supported.

What do you think about it ?

@romainneutron
Copy link
Contributor Author

IMO, this quick fix adds an important missing feature for 2.1, and I propose to add a signal emitter method in 2.2

@fabpot
Copy link
Member

fabpot commented Aug 30, 2012

scheduled for 2.2.

@travisbot
Copy link

This pull request passes (merged b62d1dd into 569e29d).

@romainneutron
Copy link
Contributor Author

I've added support for posix signals

@travisbot
Copy link

This pull request passes (merged 742ccdca into 569e29d).

@travisbot
Copy link

This pull request passes (merged 728bd4b9 into 2cf50b7).

@travisbot
Copy link

This pull request passes (merged cb1fba7b into 2cf50b7).

*/
public function sendSignal($sig)
{
if (true !== $this->isRunning()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (!$this->isRunning()) {

@travisbot
Copy link

This pull request passes (merged df0a963 into 2cf50b7).

@sstok
Copy link
Contributor

sstok commented Aug 31, 2012

Do you really need posix to send signals?
kill -s [signal] [pid] works to I guess.

@romainneutron
Copy link
Contributor Author

Do you mean to send signal via another Process ?

@sstok
Copy link
Contributor

sstok commented Aug 31, 2012

If I understand correctly, yes.

posix_kill() does nothing more then a kill command couldn't do.
And I mean using exec() or something, so using the Process would work to.

@romainneutron
Copy link
Contributor Author

posix extension is very common on *nix PHP packages.

Using posix_kill instead of exec brings human readable exception message and is cheaper in term of overhead especially if you send lots of signals.

Sending a signal with an exec is still possible and easy to do as this PR gives public access to the Pid.

@boombatower
Copy link
Contributor

Is there a reason not to use proc_terminate() since it does not require an additional extension?

@romainneutron
Copy link
Contributor Author

proc_terminate is used to signal a process that it should terminate ; this method works on non-posix systems and is not about sending a signal but terminate it.

posix_kill is about sending posix signals and does not imply the end of the process.

For example, this code does not stop the process but just send the SIGCONT posix signal :

posix_kill($pid, SIGCONT);

@romainneutron
Copy link
Contributor Author

My bad, you are right, proc_terminate correctly handles posix signals, I'm gonna update the PR

@romainneutron
Copy link
Contributor Author

By the way, I realized that after having realized multiple tests, both methods are wrong because the command pid and signal are returned against the immediate process whereas the real command is a child of the process.

it's due to the line :

$this->commandline = '('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code';

I think it's related to #5430

@boombatower
Copy link
Contributor

Since talking about this:

$this->commandline = '('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code';

Two things, 1) this makes it impossible to get back the actual command the process was constructed with which seems poor (could keep two variables), and 2) this generated another sh process that gets orphaned quite easily if the actual process is killed which just creates a memory leak.

Do we actually need that and is it better than just dealing with the bug? Seems like it creates a new problem.

@romainneutron
Copy link
Contributor Author

This is a hacky patch for getting the exitcode when PHP is compiled with the --enable-sigchild option. This option seems required when dealing with Oracle driver (see this article).

When this option is enabled you can not retrieve the exitcode.

I have work on a dirty hack (thanks @Seldaek ) which results in this commandline :

$this->commandline = '(' . $this->commandline . '&) 3>/dev/null; code=$?; echo $code >&3 & pid=$! && echo $pid >&4; wait $pid; exit $code';

This allows us to retrieve the latest pid, which can be signaled with posix_kill but it's still a pretty dirty hack.
As we dicussed with Jordi doing that, the problem with this Process class is it has lots of workaround of workaround about PHP bugs or weird behaviors.

We can't just get rid off dealing with bug or Windows behavior, because this class would be unusable in many environments.

@schmittjoh
Copy link
Contributor

You can also do it like this:

if ($notWindows) {
    $cmd = 'exec '.$cmd;
}

$proc = proc_open($cmd);
proc_terminate($proc, $signal);

This will remove PHP's wrapper, and send signals directly to the process we are interested in. I don't know if exec causes other side-effects though.

@romainneutron
Copy link
Contributor Author

Hello @schmittjoh

The workaround introduced in symfony/process@86c20b9cab is required to get the exitcode which is required to know is the process was successful.

I don't think your code will give access to it in case we're in a --enable-sigchild environment

@schmittjoh
Copy link
Contributor

This code does not look very sane :)

but anyway, could we somehow detect whether we are in an environment which
needs this instead of adding it always?

On Sat, Sep 8, 2012 at 9:34 AM, Romain Neutron notifications@github.comwrote:

Hello @schmittjoh https://github.com/schmittjoh

The workaround introduced in symfony/process@86c20b9symfony/process@86c20b9cabis required to get the exitcode which is required to know is the process
was successful.

I don't think your code will give access to it in case we're in a
--enable-sigchild environment


Reply to this email directly or view it on GitHubhttps://github.com//pull/5391#issuecomment-8385343.

@schmittjoh
Copy link
Contributor

For reference, it was added in #5353

@romainneutron
Copy link
Contributor Author

it does not seem easy to find out if the --enable-sigchild option was used at compilation, and the only solution I found is to use the output of

phpinfo(INFO_GENERAL);

@romainneutron
Copy link
Contributor Author

Which output something like

Configure Command =>  './configure'  '--prefix=/usr/local/Cellar/php53/5.3.15' '--disable-debug' '--localstatedir=/usr/local/var' '--sysconfdir=/usr/local/etc/php/5.3' '--with-config-file-path=/usr/local/etc/php/5.3' '--enable-sockets' '--enable-pcntl' '--enable-sigchild'
Registered Stream Filters => convert.iconv.*, string.rot13, string.toupper, string.tolower, string.strip_tags, convert.*, consumed, dechunk
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
default_charset => no value => no value
realpath_cache_size => 16K => 16K
realpath_cache_ttl => 120 => 120
user_ini.cache_ttl => 300 => 300
Schema Support => enabled
Phar: PHP Archive support => enabled
Phar-based phar archives => enabled
Tar-based phar archives => enabled
ZIP-based phar archives => enabled
Phar based on pear/PHP_Archive, original concept by Davey Shafik.
phar.cache_list => no value => no value
SQL connection charset => utf8
session.cache_expire => 180 => 180
session.cache_limiter => nocache => nocache
session.hash_bits_per_character => 5 => 5
session.referer_check => no value => no value
Schema support => enabled
Classes => AppendIterator, ArrayIterator, ArrayObject, BadFunctionCallException, BadMethodCallException, CachingIterator, DirectoryIterator, DomainException, EmptyIterator, FilesystemIterator, FilterIterator, GlobIterator, InfiniteIterator, InvalidArgumentException, IteratorIterator, LengthException, LimitIterator, LogicException, MultipleIterator, NoRewindIterator, OutOfBoundsException, OutOfRangeException, OverflowException, ParentIterator, RangeException, RecursiveArrayIterator, RecursiveCachingIterator, RecursiveDirectoryIterator, RecursiveFilterIterator, RecursiveIteratorIterator, RecursiveRegexIterator, RecursiveTreeIterator, RegexIterator, RuntimeException, SplDoublyLinkedList, SplFileInfo, SplFileObject, SplFixedArray, SplHeap, SplMinHeap, SplMaxHeap, SplObjectStorage, SplPriorityQueue, SplQueue, SplStack, SplTempFileObject, UnderflowException, UnexpectedValueException
Apple_PubSub_Socket_Render => /tmp/launch-A1ff2n/Render
SSH_AUTH_SOCK => /tmp/launch-FgNsTv/Listeners
Apple_Ubiquity_Message => /tmp/launch-2sqxYo/Apple_Ubiquity_Message
DISPLAY => /tmp/launch-6wDsx2/org.x:0
_SERVER["Apple_PubSub_Socket_Render"] => /tmp/launch-A1ff2n/Render
_SERVER["SSH_AUTH_SOCK"] => /tmp/launch-FgNsTv/Listeners
_SERVER["Apple_Ubiquity_Message"] => /tmp/launch-2sqxYo/Apple_Ubiquity_Message
_SERVER["DISPLAY"] => /tmp/launch-6wDsx2/org.x:0

@schmittjoh
Copy link
Contributor

That's also what Jordi mentioned on the PR.

In my benchmarks it takes about 50 microseconds which seems acceptable if
it helps to solve this problem.

On Sat, Sep 8, 2012 at 9:47 AM, Romain Neutron notifications@github.comwrote:

it does not seem easy to find out if the --enable-sigchild option was used
at compilation, and the only solution I found is to use the output of

phpinfo(INFO_GENERAL);


Reply to this email directly or view it on GitHubhttps://github.com//pull/5391#issuecomment-8385407.

@romainneutron
Copy link
Contributor Author

thanks for the quick benchmark @schmittjoh :) I've to go right now, I'm gonna implement this afternoon

@Seldaek
Copy link
Member

Seldaek commented Sep 8, 2012

Indeed at this point given the amount of hackery needed for the sigchild support it might be best to only enable it when needed. On the other hand, it is more likely we'll have regressions since not many people will test it if it's only enabled sometimes. It might be good to have a switch like the enableWindowsCompatbilitylala() so that you can run tests with and without the sigchild workarounds at least, to see if the result is consistent even on builds without sigchild.

@boombatower
Copy link
Contributor

I understand that the stuff is a workaround, but it introduces more weird behavior than it's worth in my opinion...or at the least only enable will absolutely required/requested.

@romainneutron
Copy link
Contributor Author

This PR is replaced by #5476, feel free to comment

fabpot added a commit that referenced this pull request Apr 14, 2013
This PR was squashed before being merged into the master branch (closes #5476).

Discussion
----------

[Process] Add signal and getPid methods

Bug fix: no
Feature addition: yes
Backwards compatibility break: no
Symfony2 tests pass: yes
License of the code: MIT

This PR replaces #5391 ; it adds :

 - sigchild compatibility mode. This means that if you activate it you have access to this exitcode of the process in case your php has been compiled with --enable-sigchild. This can happen when you deal with Oracle databases.

```php
$process->setEnhanceSigchildCompatibility(true);
```

 - `getPid` method to get the actual process identifier of the process

```php
$process->getPid();
```

 - `signal` method to send Posix signal to the process

```php
$process->signal(SIGHUP);
```

 - Add optionnal `$signal` as second argument to `stop`method. If provided, the signal is sent at timeout to the process. Example of use :

```php
$process->stop(5, SIGKILL);
```

Tests have been enhanced and now run both sigchild / non-sigchild mode.

By the way, tests are successful with a PHP compiled with the --enable-sigchild option ;)

Commits
-------

5ed2737 [Process] Add signal and getPid methods
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants