Jump to content

pcntl_exec("garbage") and pcntl_wait($status)


jefftanner

Recommended Posts

QUESTION: If pcntl_exec() fails (returns FALSE), then is there any way to get the reason (exit code) why what executed had failed?

 

To start, if I try to execute an non-existent command "garbage" in the command line, then it fails with an exit code of 127:

$ garbage
bash: garbage: command not found
$ echo $?
127

 

Next, I have a very simple php script test_exit.php:

<?php
exit(127);
?>

And I try to execute in the command line, then it also fails with an exit code of 127:

$ php test_exit.php
$ echo $?
127

 

Now I want to try the previous executions using PHP process controls: pcntl_fork, pcntl_exec, and pcntl_wait, etc...

 

My PHP process controls test script is as follows test_pcntl.php:

<?php
switch ($cid = pcntl_fork()) {
case -1:
	die('could not fork');

case 0:
	// Child Fork, set alarm and execute command
	pcntl_alarm(60);

	$cid = getmypid();
	print "we are in pid child $cid BEFORE\n";		

	$result = pcntl_exec($pathBinaryExecutable, $args);

	print "we are in pid child $cid AFTER, indicating that pcntl_exec() failed.\n";
	print "pid child $cid pcntl_exec() result: " . var_export( $result, TRUE ) . "\n";	

	break;

default:
	// Parent Fork, wait for return of child process
	$cid = pcntl_wait($status); 
	if(pcntl_wifexited($status)) {
		$exit_code = pcntl_wexitstatus($status);
		print "pid child $cid returned exit code: $exit_code.\n";
	}
	else if (pcntl_wifstopped($status)) {
		$stop_signal = pcntl_wstopsig($status);
		print "pid child $cid is currently stopped: $stop_signal.\n";
	}
	else if (pcntl_wifsignaled($status)) {
		$terminate_signal = pcntl_wtermsig($status);
		print "pid child $cid terminated due to a signal $terminate_signal.\n";
	}
	else {
		print "child $cid was unnaturally terminated.\n";
	}
}
?>

 

If in the Child fork, pcntl_exec() is passed php script test_exit.php:

$pathBinaryExecutable = "/usr/local/bin/php";
$args = array( "/home/jeff/public_html/php/test_exit.php" );

 

Then execution of this test script will return the expected exit code of 127:

$ php test_pcntl.php
we are in pid child 23512 BEFORE
we are in parent 23511 pre wait child 23512 BEFORE
we are in parent 23511 post wait child 23512 AFTER
pid child 23512 -- status 32512.
pid child 23512 returned exit code: 127.

 

Now if in the Child fork, pcntl_exec() is passed the non-existent command garbage:

$pathBinaryExecutable = "garbage";
$args = array();

 

Then execution of this test script does not return the expected exit code of 127:

$ php test_pcntl.php
we are in pid child 23609 BEFORE
we are in pid child 23609 AFTER, indicating that pcntl_exec() failed.
pid child 23609 pcntl_exec() result: false
we are in parent 23608 pre wait child 23609 BEFORE
we are in parent 23608 post wait child 23609 AFTER
pid child 23609 -- status 0.
pid child 23609 returned exit code: 0

 

So, at this point, the parent process thinks that the child process has succeeded because the exit code is zero (0), and not the expected 127.

 

What can I do to my code to determine why pcntl_exec() had failed, AND to determine why pcntl_wait() did not return an exit status of 127?

 

Thanks

 

-- Jeff in Seattle

Link to comment
Share on other sites

I think that code of 127 is generated by the shell itself.  If you try to execute a program that doesn't exist, then of course no program will be executed.  If no program is executed, what is the exit status of the program that didn't run?  There is none.  So the shell creates a "dummy" exit status of 127, to allow scripts to know that the command failed.

 

To replicate this in php, you would have your child return the dummy status of 127 of the exec fails.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.