Skip to content

Make usleep() and time_nanosleep() alertable on Windows - #24399

Open
nicolas-grekas wants to merge 3 commits into
php:PHP-8.4from
nicolas-grekas:windows-alertable-sleep
Open

nicolas-grekas wants to merge 3 commits into
php:PHP-8.4from
nicolas-grekas:windows-alertable-sleep

Conversation

@nicolas-grekas

@nicolas-grekas nicolas-grekas commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Allow APCs to interrupt usleep() and time_nanosleep() on Windows, as they already can with sleep(). time_nanosleep() reports the remaining duration, and time_sleep_until() resumes waiting until its deadline.

I spotted this while working on FrankenPHP and its ability to forcibly shutdown threads.

@nicolas-grekas
nicolas-grekas force-pushed the windows-alertable-sleep branch from 4424d99 to dffe371 Compare October 18, 2026 07:20

@arnaud-lb arnaud-lb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks right to me, but I would like another review

Comment thread win32/time.c Outdated
Comment thread ext/standard/tests/general_functions/sleep_alertable_win32.phpt Outdated
Comment thread win32/time.c
Comment on lines +96 to +98
zend_hrtime_t elapsed = zend_hrtime() - start;
time_t seconds = rqtp->tv_sec - (time_t) (elapsed / ZEND_NANO_IN_SEC);
long nanoseconds = rqtp->tv_nsec - (long) (elapsed % ZEND_NANO_IN_SEC);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A queued APC with a 1s callback makes time_nanosleep(2, 0) report ~1s remaining although no sleep occurred. Please exclude callback time from the remainder while preserving time_sleep_until() deadline.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done for APCs that are already queued when the sleep starts. nanosleep() now runs them first and reports the full duration as remaining.

An APC that arrives during the sleep runs before the wait returns. I don't see a way to separate its runtime from the time slept.

time_sleep_until() now resumes against its deadline instead of using the remainder.

…time slept

time_sleep_until() now resumes against its deadline. The test resolves
undecorated kernel32.dll exports, so that it also works on x86.
@nicolas-grekas

Copy link
Copy Markdown
Contributor Author

Thanks for the reviews, comments addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants