php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #78548 pcntl_signal_names() -> array of compiled-in signal labels
Submitted: 2019-09-16 04:38 UTC Modified: 2019-11-07 11:02 UTC
From: asmqb7 at gmail dot com Assigned:
Status: Open Package: PCNTL related
PHP Version: Irrelevant OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: asmqb7 at gmail dot com
New email:
PHP Version: OS:

 

 [2019-09-16 04:38 UTC] asmqb7 at gmail dot com
Description:
------------
I recently wanted a long-running application to print out something like "Exiting on SIGINT (2)" at exit.

Everything was easy to get working - except for actually determining what signal maps to what label. This isn't trivial to do because

a) Signal numbers are OS-specific.

Glancing at https://elixir.bootlin.com/linux/v4.3/source/arch/x86/include/uapi/asm/signal.h#L38 and https://www.freebsd.org/cgi/man.cgi?query=signal&manpath=FreeBSD+12.0-RELEASE, I see

- SIGSTKFLT is 16 on Linux and SIGURG on FreeBSD
- SIGSTOP is 19 on Linux and 16 on FreeBSD

So the same number can be different identifiers, and the same identifier can be different numbers. Point already probably known but ok.

b) Signal support can be compiled out of PHP based on #defines - see https://github.com/php/php-src/blob/99ce142f6e37e803ce7c0fdaece79b9813c33543/ext/pcntl/pcntl.c#L258

With both of these things in mind, the only workable approach was to hardcode a list and fill it in as best as I could. This approach is listed is in the Test Script section below.

Far better would be a function, named as in the summary or with any other sensible name, that returns any of

- ['SIGHUP', 'SIGINT', ...]
- ['SIGHUP' => 1, 'SIGINT' => 2, ...]
- [1 => 'SIGHUP', 2 => 'SIGINT', ...]

All three provide equivalent levels of functionality, because get_defined_constants() maps the labels to their correct values. To be extremely specific, the sole purpose of this function is to provide a list of which signals are *defined*.

Using get_defined_constants() is unworkable because...

Array
(
<irrelevant; snipped>
    [SIG_IGN] => 1
    [SIG_DFL] => 0
    [SIG_ERR] => -1
    [SIGHUP] => 1
    [SIGINT] => 2
    [SIGQUIT] => 3
<rest of defined signals; snipped>
    [SIGBABY] => 31
    [SIGRTMIN] => 34
    [SIGRTMAX] => 64
<irrelevant; snipped>
    [SIG_BLOCK] => 0
    [SIG_UNBLOCK] => 1
    [SIG_SETMASK] => 2
<irrelevant; snipped>
)

...it lumps the signal names in with a bunch of other things that have values that clash with signal values, so when I didn't filter the list properly (/^SIG[^_]/) my final list was like [SIG_DFL, SIG_IGN, SIG_UNBLOCK, SIG_SETMASK, SIGQUIT] - because SIG_DFL has a value of -1, and SIG_UNBLOCK (which overwrote SIGHUP) a value of 1.

The secondary implicit purpose of the function I describe is to return an array that _only_ has signal names in it.

The chances of pcntl's constants changing substantively anytime soon are VERY unlikely, but... no. I'm not parsing the output of get_defined_constants(). That specific brand of "just make it work" is the kind of hand-wavy programming that fails years later in interesting and sometimes catastrophic ways, and is what got PHP its reputation as a poor-quality environment.

Test script:
---------------
$pcntl_constants = get_defined_constants(true)['pcntl'];
foreach ([
	'SIGHUP',  'SIGPIPE',   'SIGXFSZ',
	'SIGINT',  'SIGALRM',   'SIGVTALRM',
	'SIGQUIT', 'SIGTERM',   'SIGPROF',
	'SIGILL',  'SIGSTKFLT', 'SIGWINCH',
	'SIGTRAP', 'SIGCLD',    'SIGPOLL',
	'SIGABRT', 'SIGCHLD',   'SIGIO',
	'SIGIOT',  'SIGCONT',   'SIGPWR',
	'SIGBUS',  'SIGSTOP',   'SIGSYS',
	'SIGFPE',  'SIGTSTP',   'SIGBABY', 
	'SIGKILL', 'SIGTTIN',   'SIGRTMIN', 
	'SIGUSR1', 'SIGTTOU',   'SIGRTMAX',
	'SIGSEGV', 'SIGURG',    
	'SIGUSR2', 'SIGXCPU'
] as $siglabel) {
	if (isset($pcntl_constants[$siglabel])) {
		$siglabels[$pcntl_constants[$siglabel]] = $siglabel;
	}
}
// The list is formatted as columns (current fad :) ) so fix it
ksort($siglabels);
// Do something with $siglabels
var_dump($siglabels);

Expected result:
----------------
The test script contains a user-supplied array of signals. I'd like to not have to provide this.

Actual result:
--------------
I'd like to have a magic function that, notwithstanding a bit of processing to get the results into the format I want, gives me a list of $siglabels without my having to supply them.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-09-16 09:38 UTC] cmb@php.net
-Summary: Feature request: pcntl_signal_names() -> array of compiled-in signal labels +Summary: pcntl_signal_names() -> array of compiled-in signal labels -Type: Bug +Type: Feature/Change Request
 [2019-11-07 11:02 UTC] nikic@php.net
-PHP Version: 7.4.0RC1 +PHP Version: Irrelevant
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Apr 24 23:01:34 2024 UTC