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.
This commit is contained in:
parent
d5c2ed6b14
commit
281727261d
@ -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<BUrlRequest*>(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<BUrlRequest*>(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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user