<div dir="ltr"><div dir="ltr"><h3></h3><h3><font size="2"><span style="font-weight:normal">Okay, here we go:</span></font></h3>I have debugged and made a patch based on todays trunk (attached) for a fpwebsocketclient recovery/shutdown problem on Linux with OpenSSL. After a network interruption, the client could remain active or “reconnecting” while receiving no further data until the application is restarted. During reconnect/shutdown I also saw a SIGSEGV with the reader thread inside SSL_read.<br><br>Cause: fpwebsocketclient did not always stop and join its reader thread before the connection and OpenSSL objects are destroyed. It also failed to act on irClose. The result could be either a stale connection that never received data again after a network interruption, or a SIGSEGV when transport cleanup raced with SSL_read.<br><br>The best solution was to fix this inside FPC: make the message pump own the reader thread, wake a genuinely stuck socket when necessary, join the reader, and only then destroy the connection and TLS objects. I have modified my local files and done successful runtimes tests. The rest of the fpc websocket code should be unaffected.<br><br>Proposed changes <br>    • The pump should own a named, non-self-freeing thread using FreeOnTerminate := False.<br>    • Execute, Terminate, and destruction should be idempotent.<br>    • Shutdown should follow this order:<br>        1. Request thread termination.<br>        2. Allow the bounded polling loop a short opportunity to exit normally.<br>        3. If it remains blocked, wake the socket with fpShutdown(..., SHUT_RDWR).<br>        4. Join and free the reader thread.<br>        5. Only afterward close and free the connection, transport, and TLS objects.<br><br>The wake operation must be raw socket shutdown only. Calling the TLS handler’s Shutdown, SSL_shutdown, or freeing OpenSSL state while another thread is inside SSL_read recreates the race.<br><br>ReadConnections should also process irClose: unregister the connection, mark the client inactive, and notify its owner, preferably after releasing the pump-list lock.<br><br>Because the reader currently holds the main connection-list lock while reading, termination needs a separate cold-path transport registry or another safe snapshot. This requires no additional per-message or hot-path locking.<br><br>For compatibility, socket interruption should only be the fallback for a reader that did not stop normally. Healthy connections should not be unconditionally shut down merely because the pump was stopped.<br><br><br>More in depth, the problems appear to be:<br><br>TWSThreadMessagePump.Terminate can return without proving that the worker has stopped. The timeout path clears the thread reference, allowing the connection, transport, or TLS objects to be freed while the worker may still be inside CheckIncoming/SSL_read.<br>ReadConnections ignores the irClose result, so a peer-closed connection can remain registered and appear active.<br>WaitFor alone is not sufficient: select is bounded, but after the first bytes of a frame arrive, reading the remainder of a partial WebSocket frame or TLS record can block indefinitely.<br><br>Suggested changes i detail:<br><br>Make the pump own its thread: create it suspended, set FreeOnTerminate := False, publish the reference, then start it.<br><br>Make Execute, Terminate, and destruction idempotent.<br><br>During termination, first request termination and allow a short bounded interval for the normal polling loop to exit.<br><br>If the reader is still running, wake it with raw fpShutdown(Socket.Handle, SHUT_RDWR), then call WaitFor and free the thread.<br><br>Do not call TSocketHandler.Shutdown, SSL_shutdown, close the descriptor, or free transport/TLS objects before the reader has joined. The <br>OpenSSL socket handler’s shutdown path destroys SSL state and is unsafe concurrently with SSL_read.<br><br>Keep a separate cold-path registry or another safe snapshot of registered transports, because ReadConnections currently holds the main list lock while reading. The termination path must not wait for that same lock before it can wake the blocked reader.<br><br>Handle irClose by safely unregistering the connection, marking the client inactive, and notifying its owner—preferably after releasing the pump-list lock.<br><br>Preserve normal client-processing order and existing protected signatures where practical. Raw socket interruption should be the stuck-reader fallback rather than unconditional behavior, so applications that temporarily stop and restart a healthy pump retain compatibility.<br><br>Useful regression tests would cover partial-frame/TLS-record stalls, repeated Execute/Terminate, destruction during a blocked read, peer close and OnDisconnect, and multiple clients sharing one pump.</div><div><br></div><div>/Roger</div></div>