From 281727261d82bb7be4a3b933f1ece96390854985 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 23 Jan 2014 15:48:04 +0100 Subject: [PATCH] urlRequest: interrupt syscalls using a signal Sometimes an HTTP request would get stuck in a call to connect(). While our read() and write() implementations are interrupted if you close() the socket, our connect() isn't. It would nonetheless abort the connection process, and connect would stay blocked for quite a long time. When navigating away from a page, WebKit closes all pending connections, and in our network backend this also means freeing the request object. But, the destructor can't be called until the thread has stopped running, to ensure proper cleanup. Avoid the lockup in connect by sending a signal (SIGUSR1) to the thread we want to unlock. This interrupts the syscall, and the thread exits immediately. --- src/kits/network/libnetapi/UrlRequest.cpp | 29 +++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/kits/network/libnetapi/UrlRequest.cpp b/src/kits/network/libnetapi/UrlRequest.cpp index b3168b113b..32da63513d 100644 --- a/src/kits/network/libnetapi/UrlRequest.cpp +++ b/src/kits/network/libnetapi/UrlRequest.cpp @@ -90,6 +90,7 @@ BUrlRequest::Stop() status_t threadStatus = B_OK; fQuit = true; + send_signal(fThreadId, SIGUSR1); // unblock blocking syscalls. wait_for_thread(fThreadId, &threadStatus); return threadStatus; } @@ -183,19 +184,33 @@ BUrlRequest::Status() const // #pragma mark Thread management +void +empty(int) +{ +} + + /*static*/ int32 BUrlRequest::_ThreadEntry(void* arg) { - BUrlRequest* urlProtocol = reinterpret_cast(arg); - urlProtocol->fThreadStatus = B_BUSY; + // Setup an (empty) signal handler so we can be stopped by a signal, + // witohut the whole process being killed. + struct sigaction action; + action.sa_handler = empty; + action.sa_mask = 0; + action.sa_flags = 0; + sigaction(SIGUSR1, &action, NULL); - status_t protocolLoopExitStatus = urlProtocol->_ProtocolLoop(); + BUrlRequest* request = reinterpret_cast(arg); + request->fThreadStatus = B_BUSY; - urlProtocol->fRunning = false; - urlProtocol->fThreadStatus = protocolLoopExitStatus; + status_t protocolLoopExitStatus = request->_ProtocolLoop(); - if (urlProtocol->fListener != NULL) { - urlProtocol->fListener->RequestCompleted(urlProtocol, + request->fRunning = false; + request->fThreadStatus = protocolLoopExitStatus; + + if (request->fListener != NULL) { + request->fListener->RequestCompleted(request, protocolLoopExitStatus == B_OK); }