shapeshifter Posted November 7, 2008 Share Posted November 7, 2008 I'm currently rewriting a reporting engine in PHP 5 that was originally done in Perl (ugh!) The original engine simply polled a database table for new jobs and forked a process for every one it found to process and output as required. I don't want to change that too radically, but I do want to extend this so I can pause or terminate a spawned process from within the main engine. My code is all OO. When the code forks, the child creates an object of type 'Report'. Class report has it's own signal handler method and I register the signals I want to handle in the constructor using this syntax: pcntl_signal(SIGUSR1, array(&$this, "sig_handler")); As the Report class is just a skeleton right now, for the purposes of experimentation I have created a method that simply loops round printing off some abitrary line every second. In the main engine from where the process was forked, I wait a few secs then send: posix_kill($pid, SIGUSR1); This actually works just fine as far as I can see. It inturrupts the print loop in the forked process and executes the code for the right signal. The only code I have there right now is a debug statement, and there lies my problem.... I have a static class 'Debug' which is basically a wrapper around 'print'. I call this in the Report constructor and the method that does the looping and it works just fine, but when I call Debug::Output in the signal handler, I get a "call to undefined method Debug::output()" fatal error (note lower case in method name). I also have signal handling in my main file, and this uses the static class just fine (although that's not OO (yet)), so what is going on? Once this is sorted, my other problem is that I want to be able to get info back from the spawned process without it exiting. Can this be done without resorting to all that piping stuff? I should point out that my PHP knowledge is pretty limited and I'm working in FreeBSD 6.2. And this is a purely server-side program (would use C++ if I were allowed to, but PHP is cool). Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/ Share on other sites More sharing options...
Adam Posted November 7, 2008 Share Posted November 7, 2008 Well can't really say, would need to see some code pal! Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-684486 Share on other sites More sharing options...
shapeshifter Posted November 7, 2008 Author Share Posted November 7, 2008 Well here's a cut down version of the Report object: abstract class Report { private $pInput; public function __construct($_input) { $pInput = $_input; pcntl_signal(SIGTERM, array(&$this, "SigHandler")); pcntl_signal(SIGUSR1, array(&$this, "SigHandler")); Debug::Ouput("Report object constructed"); } private function SigHandler($signo) { Debug::Ouput("I'm the report classes sig handler!"); switch ($signo) { case SIGTERM: Debug::Ouput("handling a sigterm in report object!"); exit; break; case SIGUSR1: Debug::Ouput("handling a SIGUSR1 in report object!"); exit; break; } } public function MainLoop() { // just to show object is doing stuff while(1) { sleep(1); Debug::Output("I'm a silly child and will keep printing til I get a SIGnal"); } } } class ReportManagement extends Report { // to be done. } In the parent, the relevent code looks like this: // pulled a new job requirement blah blah, so fork a new process $pid = pcntl_fork(); Debug::Output("pid returned = $pid\n"); if ($pid == -1) { Debug::Output("fork me! Didn't work. do stuff etc"); ExitProg(); } else if (!$pid) { Debug::Output("In child no.$i\n"); $report = new ReportManagement(new Input("<xml>test</xml>")); $report->MainLoop(); } else { Debug::Output("I'm the daddy!"); sleep(5); posix_kill($pid, SIGUSR1); } This calls the child's sig handler successfully, but gives a fatal error on the Debug::Output even though that works just fine in the constructor and MainLoop methods. Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-684511 Share on other sites More sharing options...
shapeshifter Posted November 7, 2008 Author Share Posted November 7, 2008 Too hard for you all? Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-684712 Share on other sites More sharing options...
shapeshifter Posted November 10, 2008 Author Share Posted November 10, 2008 It seems so. Looks like I'll have to find a smarter forum Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-687011 Share on other sites More sharing options...
nitation Posted November 10, 2008 Share Posted November 10, 2008 you making great mistake. Through Phpfreaks, i have learn't more than you can think of. Move around and tell me if any better free php forum is available for you. Doctor~ Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-687069 Share on other sites More sharing options...
shapeshifter Posted November 10, 2008 Author Share Posted November 10, 2008 I'm just teasing. I'm surprised no one on here can help me. I'm sure far harder questions are posted here all the time. Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-687175 Share on other sites More sharing options...
premiso Posted November 10, 2008 Share Posted November 10, 2008 It could also be you just pasted your code outside of the proper tags and failed to read the posting rules. Me, if it does not have the code tags around I rarely help cause it makes it harder to know the code you are looking at is good code and not screwed up when posted. Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-687189 Share on other sites More sharing options...
shapeshifter Posted November 10, 2008 Author Share Posted November 10, 2008 Sorry, I'm new to the forum and have not yet familiarised myelf with such rules. It would have been impossible to post all of the original code verbatim (my project is spread over 11 files), but the majority of the code I posted (the 'report' class stuff) is self-contained in its own file, and nothing was omitted from that apart from the opening and closing php tags. The last bit is abridged from a main.php file. Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-687210 Share on other sites More sharing options...
Caesar Posted November 10, 2008 Share Posted November 10, 2008 Just edit your post, use <?php tags to open/close even if it isn't the entire script... and surround it with [ code ] [ /code ]...it will highlight your code accordingly and make it easier for people to look through. Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-687212 Share on other sites More sharing options...
Mark Baker Posted November 10, 2008 Share Posted November 10, 2008 I assume you have remembered declare(ticks = 1); Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-687261 Share on other sites More sharing options...
shapeshifter Posted November 11, 2008 Author Share Posted November 11, 2008 Yes, but I can't confirm it for another 9 hours or so. I know for a fact that the right handler is being called and the right switch made. It's just using the static class from within the signal handler that won't work. Call me Captain Stupid, but I can't work out how to edit my post with the code. Assumed there would be an icon or something by my posts? The help page mentions a 'modified' button I can't see for the life of me. If that sounds odd it's cos I rarely if ever use forums and work out my problems for myself. But this has me flummoxed! edit: just noticed one on this last post. can I only edit the last post, or is it cos I posted the original block of code from a different IP address? Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-687275 Share on other sites More sharing options...
Mark Baker Posted November 11, 2008 Share Posted November 11, 2008 I assume you're getting the Debug::Ouput("I'm the report classes sig handler!"); but not the Debug::Ouput("handling a SIGUSR1 in report object!"); or is it failing on both? What exactly is the fatal error you're getting? Is it possible that the parent process is terminating immediately after issuing the posix_kill() and taking the child process down with it? And $pInput = $_input; should probably be $this->pInput = $_input; though that has nothing to do with your problem, and I'm assuming it's just a typo in copying the skeleton rather than the real code. Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-687305 Share on other sites More sharing options...
shapeshifter Posted November 11, 2008 Author Share Posted November 11, 2008 The fatal error is: Fatal error: Call to undefined method Debug::ouput() And I can confirm that the signal handler fails on any use of the Debug static class (even though I can use Debug in the other methods just fine). Otherwise it works just how it should. I should have said that I have a while(1) loop at the bottom of my main file to prevent the parent exiting, so that's not the problem. I use 'declare(ticks=1)' right at the top of my main file. Tried adding it at the top of the report class too, but has no effect either way. And you were very diplomatic, Mark, but that is a bug. Hadn't noticed it cos it's still just a skeleton. I come from a C++ background so not used to HAVING to use 'this'. Bit of a pain, but PHP is still a million times better than perl [cough! spit!] Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-687815 Share on other sites More sharing options...
Mark Baker Posted November 11, 2008 Share Posted November 11, 2008 Debug::Ouput("I'm the report classes sig handler!"); Debug::Ouput("handling a sigterm in report object!"); Debug::Ouput("handling a SIGUSR1 in report object!"); Debug::Output("I'm a silly child and will keep printing til I get a SIGnal"); And there I think we've got it... and a silly typo (ever the diplomat) when it comes down to it. Take a very careful look at the above, particularly the spelling of Output Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-687901 Share on other sites More sharing options...
shapeshifter Posted November 11, 2008 Author Share Posted November 11, 2008 Well how dumb am I? I did all the hard work with processes and signal handling then do sommat stupid. Very typical of me. Thanks Mark. As a lame excuse, I was distracted by the lower case 'o' when I always give function/method names upper case starting letters. Now my problem is passing information between processes other than pre-defined signals (like how long a job took to run etc). Will I have to resort to pipes? Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-688021 Share on other sites More sharing options...
Mark Baker Posted November 11, 2008 Share Posted November 11, 2008 Well how dumb am I? I did all the hard work with processes and signal handling then do sommat stupid. Very typical of me.As a lame excuse, I was distracted by the lower case 'o' when I always give function/method names upper case starting letters.Don't get me started :-) I spent nearly an hour today tring to figure out why a function I was profiling for performance wasn't working... finally realised that I was defining my $testdata = array(...) and calling the function using $result = factors($testData); Now my problem is passing information between processes other than pre-defined signals (like how long a job took to run etc). Will I have to resort to pipes?I was intrigued by your problem because I wrote a similar threaded scheduler script, with each child process spawning off grandchildren as well; and I chose to use socket pairs to communicate between the parent and child... and maintained a listener on the top-level parent so that I could telnet to it and issue commands directly that would then be filtered down to the appropriate level for requesting status data, issuing shutdown commands, etc. Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-688035 Share on other sites More sharing options...
shapeshifter Posted November 13, 2008 Author Share Posted November 13, 2008 I'm just reading up on socket pairs now, although I could get around the issue by giving extra functionality to the child processes (like limited reading and writing to the report-queue in the database). I don't need the telnet side of things as I plan to put an interactive web-front-end over the report queue which is constantly monitored by the parent. If I get stuck I'll be back! Thanks again for finding my typo, Mrak (sic) Quote Link to comment https://forums.phpfreaks.com/topic/131766-signal-handling-in-an-object-in-a-forked-process/#findComment-689176 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.