M1I07: MasterProxy (SCM_RIGHTS)#64
Merged
Merged
Conversation
- Implements SocketProxyInterface with TCP socket, sysvmsg queue, and Unix socket pair - accept() dispatches fd to workers via socket_sendmsg() with SCM_RIGHTS - isSupported() checks for msg_get_queue and socket_sendmsg - Tests: interface compliance, socket creation, accept, isSupported Closes #9
s2x
commented
May 1, 2026
Contributor
Author
s2x
left a comment
There was a problem hiding this comment.
Review Summary — Round 1
| # | Severity | File:Line | Finding |
|---|---|---|---|
| 1 | MEDIUM | MasterProxy.php:43 |
$streams[1] from stream_socket_pair leaked — never stored or closed |
| 2 | MEDIUM | MasterProxy.php:66 |
Reflection to access Connection::$resource breaks encapsulation |
| 3 | LOW | MasterProxy.php:69 |
@ suppresses socket_sendmsg failures silently |
Follow-up Observations
- Message queue created but not yet wired —
msg_get_queue()at line 36 creates a kernel-persistent queue, but no messages are sent or received. If an exception is thrown after this line (e.g.stream_socket_pairfails), the queue is orphaned. Consider wrapping in try-catch with cleanup, or deferring queue creation until the coordination logic is implemented. - Missing negative test cases — no tests for
msg_get_queuefailure,stream_socket_pairfailure, orsocket_sendmsgfailure paths. Low priority for now but recommended before merging. - Reflection in tests too —
MasterProxyTest::getSocketResource()uses the same reflection pattern to accessSocket::$resource. Tests using reflection are more acceptable, but a public getter onSocketcould clean this up.
What's Fine ✔️
- Interface contract fully implemented (
createSocket,accept,isSupported) - All acceptance criteria from M1.07 milestone doc satisfied
SCM_RIGHTSfd passing structure is correct- Test coverage for happy paths (socket creation, accept flow,
isSupported()) is present - Code follows existing proxy patterns (
ForkSharedProxy,ReusePortProxy) for socket creation
Contributor
Author
|
Findings status after a6485bd:
|
s2x
commented
May 1, 2026
Contributor
Author
s2x
left a comment
There was a problem hiding this comment.
Review Summary — Round 1
| # | Severity | File:Line | Finding |
|---|---|---|---|
| 1 | HIGH | src/Server/Socket/MasterProxy.php:49 |
socket_strerror(socket_last_error()) used after stream_socket_pair() failure — will produce bogus error message |
| 2 | HIGH | src/Server/Socket/MasterProxy.php:36 |
msg_get_queue() queue never stored or removed — kernel resource leak (IPC resources persist after process exit) |
| 3 | MEDIUM | src/Server/Socket/MasterProxy.php:36 |
Message queue created but never used — no msg_send() call; dead code or incomplete |
| 4 | MEDIUM | src/Server/Socket/MasterProxy.php:76 |
socket_sendmsg() return value not checked — silent failure, broken connection returned |
| 5 | MEDIUM | src/Server/Socket/MasterProxy.php:63 |
Reflection access to private Socket::$resource — fragile coupling to internal implementation |
| 6 | MEDIUM | src/Server/Socket/MasterProxy.php:55 |
socket_last_error() used after socket_import_stream() — non-socket function, same bogus-error bug |
| 7 | MEDIUM | tests/Server/Socket/MasterProxyTest.php:31 |
Queue creation is not actually tested — test only checks createSocket() return type, never verifies queue exists |
| 8 | LOW | src/Server/Socket/MasterProxy.php:17 |
$protocol parameter accepted but unused — socket always AF_INET, SOCK_STREAM, SOL_TCP |
Follow-up Observations
- The
$queueshould be stored as a class property — when the Worker is implemented,msg_send()will be needed to signal workers that an fd is available on the socket pair. - Missing destructor/cleanup for the socket pair and message queue.
- The
getSocketResource()reflection helper is duplicated betweenMasterProxyandMasterProxyTest— consider adding a publicSocket::getResource(): \Socketmethod instead. - The
@onsocket_sendmsg()should be replaced with a proper return-value check and fallback (close accepted socket on failure). - Re-evaluate whether the message queue is actually needed for this milestone (M1I07) or if it belongs in a future Worker milestone.
What's Fine ✔️
- All acceptance criteria from the issue and milestone doc are nominally met.
- Both required files created.
isSupported()implementation is correct.- Test covers the interface check, socket creation,
accept(), andisSupported().
s2x
commented
May 1, 2026
Contributor
Author
s2x
left a comment
There was a problem hiding this comment.
Review Summary — Round 1
| # | Severity | File:Line | Finding |
|---|---|---|---|
| 1 | HIGH | MasterProxy.php:41 |
socket_last_error() called after stream_socket_pair() — wrong error domain |
| 2 | HIGH | MasterProxy.php:31 |
msg_get_queue() kernel resource created and permanently leaked |
| 3 | MEDIUM | MasterProxy.php:53 |
fclose($streams[1]) closes worker end → SCM_RIGHTS sends into void |
| 4 | MEDIUM | MasterProxy.php:77 |
@socket_sendmsg return value never checked — silent fd transfer failure |
| 5 | LOW | MasterProxy.php:13 |
Uninitialized typed property $sendSocket — fatal error if accept() called before createSocket() |
Follow-up Observations
- Partial failure leak: If
msg_get_queue,stream_socket_pair, orsocket_import_streamfails after the TCP socket is already created/bound/listening, the socket and any earlier-created resources are leaked — no try/finally cleanup. $protocolparameter unused:createSocketignores theProtocolTypeargument and always createsAF_INET/SOCK_STREAM/SOL_TCP. This matchesForkSharedProxy/ReusePortProxyconvention, but worth documenting.- Reflection per accept call:
new ReflectionPropertyinstantiated on every hot-pathaccept(). Should be cached as a static property. ftok(__FILE__, 'M')fragile: Couples queue identity to file path. RenamingMasterProxy.phpbreaks the queue key.- No class-level docblock: Purpose of the message queue, socket pair, and SCM_RIGHTS ancillary data passing is undocumented.
iovspace character:[' ']is a standard dummy-payload idiom for SCM_RIGHTS, but non-obvious — a comment would help.- Missing negative test coverage: No tests for
msg_get_queuefailure,stream_socket_pairfailure,socket_sendmsgfailure.
What's Fine ✔️
- Interface contract fully implemented
- All 5 acceptance criteria from M1.07 milestone doc nominally satisfied
- SCM_RIGHTS structure is correct (right constants, correct cmsg format)
- Socket creation follows existing proxy patterns (SO_REUSEADDR, bind, listen)
- Test coverage for happy paths present
- No secrets, PII, or insecure crypto in the diff
Contributor
Author
|
Review Round 1 — fix status (683ad2c):
Also addressed:
Deferred (follow-ups):
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/Server/Socket/MasterProxy.phptests/Server/Socket/MasterProxyTest.phpImplements
MasterProxy— dispatcher proxy using SCM_RIGHTS socket passing via System V message queues:SO_REUSEADDR, binds, listenssysvmsgmessage queue (msg_get_queue)accept()accepts connection, dispatches fd to workers viasocket_sendmsg()withSCM_RIGHTSisSupported()checksfunction_exists('msg_get_queue') && function_exists('socket_sendmsg')Acceptance criteria
SocketProxyInterfacecreateSocket()socket_sendmsg()withSCM_RIGHTSto pass fd to workersisSupported()checks formsg_get_queueandsocket_sendmsgisSupported(), queue creationCloses #9