php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #55614 pcntl_signal() + fgetc() is not allowing me to break with CTRL+C
Submitted: 2011-09-06 03:15 UTC Modified: 2011-09-06 03:24 UTC
Votes:3
Avg. Score:4.0 ± 0.8
Reproduced:3 of 3 (100.0%)
Same Version:0 (0.0%)
Same OS:2 (66.7%)
From: i3367890 at gmail dot com Assigned:
Status: Open Package: PCNTL related
PHP Version: 5.3.8 OS: (Arch) Linux
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2011-09-06 03:15 UTC] i3367890 at gmail dot com
Description:
------------
Running the following code at the commandline as demonstrated simply does not 
work for me. It gobbles up all presses of ^C and will not quit (^\ ie CTRL+\ 
produces SIGQUIT and is useful in this situation):

  php -r "declare(ticks = 1); function quit() { print \"X\\n\"; die; } 
pcntl_signal(SIGINT, \"quit\"); fgetc(STDIN);"


Running the following, on the other hand, works for me just fine.

  php -r "declare(ticks = 1); function quit() { print \"X\\n\"; die; } 
pcntl_signal(SIGINT, \"quit\"); while(1) { sleep(1); };"

Pressing ^C shuts the script down nicely.

I see no problems with the first code example. It should work, right? Here's 
what 
strace is saying:

My console | strace console
           | (....)
           | rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
           | rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
           | read(0, 0x943e5f4, 8192)      = ? ERESTARTSYS (To be restarted)
           | --- SIGINT (Interrupt) @ 0 (0) ---
           | sigreturn()                   = ? (mask now [])
           | read(0, 0x943e5f4, 8192)      = ? ERESTARTSYS (To be restarted)
  ^C ---------------^
           | --- SIGINT (Interrupt) @ 0 (0) ---
           | sigreturn()                   = ? (mask now [])
           | read(0, 0x943e5f4, 8192)      = ? ERESTARTSYS (To be restarted)
  ^C ---------------^
           | --- SIGINT (Interrupt) @ 0 (0) ---
           | sigreturn()                   = ? (mask now [])
           | read(0, 
 (waiting) ---------^


It gets even more interesting. Setting parameter 3 to pcntl_signal, 
restart_signals, to false makes PHP gobble up one ^C *then* quit:

php -r "declare(ticks = 1); function quit() { print \"X\\n\"; die; } 
pcntl_signal(SIGINT, \"quit\", 0); fgetc(STDIN);"

Like so:
My console | strace console
           | (...)
           | rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
           | rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
           | rt_sigaction(SIGINT, {0x82d8690, ~[RTMIN RT_1], SA_INTERRUPT}, 
{SIG_DFL, [], 0}, 8) = 0
           | rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
           | rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
           | read(0, 0x9e985f8, 8192)      = ? ERESTARTSYS (To be restarted)
   ^C --------------^
           | --- SIGINT (Interrupt) @ 0 (0) ---
           | sigreturn()                   = ? (mask now [])
           | read(0, 0x9e985f8, 8192)      = ? ERESTARTSYS (To be restarted)
   ^C --------------^
           | --- SIGINT (Interrupt) @ 0 (0) ---
           | sigreturn()                   = ? (mask now [])
           | rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
   ! -->   | write(1, "X\n", 2)            = 2
           | rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], ~[KILL STOP RTMIN RT_1], 
8) 
= 0
           | rt_sigprocmask(SIG_SETMASK, ~[KILL STOP RTMIN RT_1], NULL, 8) = 0
           | close(2)                      = 0
           | close(1)                      = 0
           | (...)

As you can see from my exclamation, *the custom quit function is WORKING* in the 
second example, just not straight away. PHP seems to be having indigestion with 
the restart_syscalls bit...?

I wasn't sure what to put in what boxes since there were multiple scripts and 
backtraces (if you could call them such) so I put them all here. Hope that's 
okay.

i336


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-09-06 03:24 UTC] i3367890 at gmail dot com
I forgot to mention something!

In the first script pressing a key (any key) causes PHP to shut down properly. 
Here's what it looks like:

My console | strace console
           | (....)
           | rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
           | read(0, 0x8b825f8, 8192)      = ? ERESTARTSYS (To be restarted)
  ^C ---------------^
           | --- SIGINT (Interrupt) @ 0 (0) ---
     I     | sigreturn()                   = ? (mask now [])
  pressed  | read(0, "d", 8192)            = 1
    "d" -------------^
           | rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
   ! -->   | write(1, "X\n", 2)            = 2
           | rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], ~[KILL STOP RTMIN RT_1], 
8) = 0
           | rt_sigprocmask(SIG_SETMASK, ~[KILL STOP RTMIN RT_1], NULL, 8) = 0
           | close(2)                      = 0
My console | strace console
           | (....)

=======
 NOTE:
=======
If fgetc(STDIN) does not return immediately after a single character - it 
doesn't on my system, it waits for a newline - you might need to run "stty 
cbreak". When you're done run "stty -cbreak" if you want to switch whatever 
cbreak does back off, or just close the terminal.

i336
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sun May 19 16:01:26 2019 UTC