Skip to content

Reads and writes with a zero timeout need to be non-blocking. - #6293

Open
NathanFreeman wants to merge 1 commit into
swoole:masterfrom
NathanFreeman:zero_timer
Open

NathanFreeman wants to merge 1 commit into
swoole:masterfrom
NathanFreeman:zero_timer

Conversation

@NathanFreeman

Copy link
Copy Markdown
Member

No description provided.

@matyhtf

matyhtf commented Oct 13, 2026

Copy link
Copy Markdown
Member

Thanks for the fix. Please address the following issues before merging.

1. Preserve native PHP behavior for zero-timeout writes

For a blocking TCP stream with stream_set_timeout($stream, 0, 0), once its send buffer is full, I reproduced the following difference on Linux / PHP 8.4:

Behavior Native PHP This PR
fwrite() false 0
stream_get_meta_data($stream)['timed_out'] true false

In socket_write(), the new condition routes a blocking stream with zero timeout through send_once(), but the existing error handling converts EAGAIN into a zero-byte write. This loses the distinction between a blocking stream whose timeout has expired and an explicitly non-blocking stream. Applications checking for false or timed_out may keep retrying.

Please keep the immediate write attempt, but preserve native PHP's failure return and timeout state when a blocking zero-timeout write cannot proceed. Explicitly non-blocking streams should retain their zero-byte-write behavior. See PHP's socket stream write implementation.

2. Make the write regression test actually reach a full send buffer

The current test writes only 1 MiB once. On my machine, all 1 MiB was written immediately, so the test never exercised the full-buffer condition. Its assertion also accepts false, 0, and a complete write, which cannot detect the compatibility issue above.

Please fill the buffer in non-blocking mode until no further bytes can be written, then switch back to blocking mode, set the zero timeout, and verify the write result, timed_out, and eof against native PHP. Cover explicitly non-blocking writes separately.

Please also replace the fixed 10-second server sleep with explicit synchronization, and bound the polling loop in the read test so that a regression cannot hang the test indefinitely.

The read-side approach is consistent with native PHP. The four new tests and the existing coroutine timeout test passed in my Linux / PHP 8.4 build, but the additional native-PHP comparison exposed the write-side gap above.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants