php / php/doc-en

curl and other native libraries block pcntl async signal propagation

Open
#1,712 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug Extension: pcntl Status: Needs Triage
Dominant language
XML
Stars
596
Forks
890
Avg merge
1d 15h
Merged PRs (30d)
55

Description

Description

The following code:

<?php

pcntl_async_signals(true);

$handler = function() {
	echo 'HANDLER CALLED' . PHP_EOL;
	pcntl_alarm(1);
};

pcntl_signal(SIGALRM, $handler);
pcntl_alarm(1);

while (true) {
    $ch = curl_init();
    //curl_setopt($ch, CURLOPT_NOPROGRESS, false);
    //curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function() {});
    curl_setopt($ch, CURLOPT_URL, 'http://localhost/timeout.php');
    curl_exec($ch);
    curl_close($ch);
}

Gives following output:

Request started
HANDLER CALLED
Request done

But I expected this output instead:

Request started
HANDLER CALLED
HANDLER CALLED
HANDLER CALLED
HANDLER CALLED
HANDLER CALLED
HANDLER CALLED
HANDLER CALLED
HANDLER CALLED
HANDLER CALLED
Request done

PHP main thread is blocked during the entire request, the handler is called only after that. This behaviour renders pcntl_async_signals unusable for most workloads (eg. sending heartbeats to keep connections open during long running operations). The issue is not restricted to SIGALRM only, it applies to all signals.

Such behaviour is not documented anywhere (including the RFC https://wiki.php.net/rfc/async_signals) yet the same problem actually applies to other native libraries like PDO/mysqli,... (see already reported issue for mysqli https://bugs.php.net/bug.php?id=81515)

If this is expected behaviour, it must be documented as right now it seems like the only RELIABLE way to implement specific features but it behaves unpredictably with the use of 3rd party libraries and it's very hard to debug.

Adding both curl_setopt($ch, CURLOPT_NOPROGRESS, false); and curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function() {}); fixes this particular issue but it's an undocumented required configuration and most likely just a side-effect.


Example of PDO query blocking:

<?php

pcntl_async_signals(true);

$handler = function () {
	echo 'Handler called';
	pcntl_alarm(1);
};

pcntl_signal(SIGALRM, $handler);
pcntl_alarm(1);

$conn = new PDO('mysql:host=localhost;dbname=test', 'root', 'admin');
$conn->query("SELECT SLEEP(10)");
PHP Version

8.1, 8.0

Operating System

Debian Buster, MacOS

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the pcntl_async_signals RFC and the curl and PDO examples in the issue, including the reported CURLOPT_PROGRESSFUNCTION workaround. Document when signals are dispatched during blocking native-library calls and whether the behavior is expected, with any reliable configuration or limitations stated clearly.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
documentation
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.