From 2a4f27f2094c466e5c78a57958fe9d186de43d76 Mon Sep 17 00:00:00 2001 From: Guilhem Lavaux Date: Sat, 8 May 1999 12:18:53 +0000 Subject: [PATCH 1/1] * implemented VZ's idea about creating and destroying bg threads. (PB with the destruction of waiter: I think it's a race problem but I can't localize it if someone finds it please mail it to me) * Fixed race condition in threadpsx.cpp. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2364 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/sckint.h | 10 ++-- src/common/sckint.cpp | 104 ++++++++++++++++++----------------------- src/common/socket.cpp | 27 ++++------- src/unix/threadpsx.cpp | 4 +- 4 files changed, 62 insertions(+), 83 deletions(-) diff --git a/include/wx/sckint.h b/include/wx/sckint.h index e90dfb939c..e42b7bfb9e 100644 --- a/include/wx/sckint.h +++ b/include/wx/sckint.h @@ -115,12 +115,10 @@ class wxSocketInternal { int GetFD() { return m_fd; } - void InitializeSocket(); - void FinalizeSocket(); - void PauseSocket(); - void ResumeSocket(); - void EnableWaiter(); - void DisableWaiter(); + void ResumeWaiter(); + void StopWaiter(); + void ResumeRequester(); + void StopRequester(); void QueueRequest(SockRequest *request, bool async); void WaitForEnd(SockRequest *request); diff --git a/src/common/sckint.cpp b/src/common/sckint.cpp index a177aed788..7d372c0384 100644 --- a/src/common/sckint.cpp +++ b/src/common/sckint.cpp @@ -165,14 +165,13 @@ void *SocketWaiter::Entry() if (ret == 0) // If nothing happened, we wait for 100 ms. wxUsleep(10); - else - wxYield(); */ // Check whether we should exit. - if (TestDestroy()) + if (TestDestroy()) { return NULL; - } + } + } return NULL; } @@ -320,16 +319,16 @@ void *SocketRequester::Entry() wxSocketInternal::wxSocketInternal(wxSocketBase *socket) { m_socket = socket; - m_thread_waiter = new SocketWaiter(socket, this); - m_thread_requester = new SocketRequester(socket, this); + m_thread_requester = NULL; + m_thread_waiter = NULL; m_request_locker.Lock(); } wxSocketInternal::~wxSocketInternal() { + wxASSERT(m_thread_requester == NULL); + wxASSERT(m_thread_waiter == NULL); m_request_locker.Unlock(); - delete m_thread_waiter; - delete m_thread_requester; } // ---------------------------------------------------------------------- @@ -376,82 +375,69 @@ void wxSocketInternal::ReleaseFD() m_fd_locker.Unlock(); } -// ---------------------------------------------------------------------- -// InitializeSocket: called by wxSocketBase to initialize the daemons with -// a new file descriptor and to create them -// ---------------------------------------------------------------------- -void wxSocketInternal::InitializeSocket() +void wxSocketInternal::ResumeRequester() { - wxASSERT( ((!m_thread_waiter->IsAlive() || m_thread_waiter->IsPaused()) && - (!m_thread_requester->IsAlive() || m_thread_requester->IsPaused()))); + wxThreadError err; - m_thread_waiter->m_fd = m_socket->m_fd; - m_thread_requester->m_fd = m_socket->m_fd; + wxASSERT(m_thread_requester == NULL); - if (m_thread_waiter->IsPaused()) - ResumeSocket(); - else { - wxThreadError err; + m_thread_requester = new SocketRequester(m_socket, this); + m_thread_requester->m_fd = m_socket->m_fd; - err = m_thread_waiter->Create(); - wxASSERT(err == wxTHREAD_NO_ERROR); - err = m_thread_requester->Create(); - wxASSERT(err == wxTHREAD_NO_ERROR); + err = m_thread_requester->Create(); + wxASSERT(err == wxTHREAD_NO_ERROR); - err = m_thread_waiter->Run(); - wxASSERT(err == wxTHREAD_NO_ERROR); - err = m_thread_requester->Run(); - wxASSERT(err == wxTHREAD_NO_ERROR); - } + err = m_thread_requester->Run(); + wxASSERT(err == wxTHREAD_NO_ERROR); } - -// ---------------------------------------------------------------------- -// InitializeSocket: called by wxSocketBase to destroy daemons -// ---------------------------------------------------------------------- -void wxSocketInternal::FinalizeSocket() +void wxSocketInternal::StopRequester() { - ResumeSocket(); - - m_thread_waiter->Delete(); - - // Send a signal to the thread "requester". + wxASSERT(m_thread_requester != NULL); m_socket_locker.Lock(); + + // Send a signal to the requester. if (m_requests.Number() == 0) m_socket_cond.Signal(); + m_socket_locker.Unlock(); - // Finish the destruction of the thread "requester". + // Finish the destruction of the requester. m_thread_requester->Delete(); -} -void wxSocketInternal::PauseSocket() -{ - DisableWaiter(); + delete m_thread_requester; + m_thread_requester = NULL; } -void wxSocketInternal::ResumeSocket() +void wxSocketInternal::ResumeWaiter() { - EnableWaiter(); -} + wxThreadError err; -void wxSocketInternal::EnableWaiter() -{ - wxASSERT(m_thread_waiter != NULL); - if (!m_thread_waiter->IsAlive() || !m_thread_waiter->IsPaused()) + if (m_thread_waiter != NULL) return; - m_thread_waiter->Resume(); + m_thread_waiter = new SocketWaiter(m_socket, this); + m_thread_waiter->m_fd = m_socket->m_fd; + + err = m_thread_waiter->Create(); + wxASSERT(err == wxTHREAD_NO_ERROR); + + err = m_thread_waiter->Run(); + wxASSERT(err == wxTHREAD_NO_ERROR); } -void wxSocketInternal::DisableWaiter() +void wxSocketInternal::StopWaiter() { - wxASSERT(m_thread_waiter != NULL); - if (!m_thread_waiter->IsAlive() || m_thread_waiter->IsPaused()) +/* + if (m_thread_waiter == NULL) return; - m_thread_waiter->Pause(); + m_thread_waiter->Delete(); + + delete m_thread_waiter; + m_thread_waiter = NULL; +*/ } // ---------------------------------------------------------------------- @@ -460,6 +446,9 @@ void wxSocketInternal::DisableWaiter() void wxSocketInternal::QueueRequest(SockRequest *request, bool async) { if (async) { + if (m_thread_requester == NULL) + ResumeRequester(); + m_request_locker.Lock(); request->done = FALSE; m_requests.Append((wxObject *)request); @@ -478,7 +467,6 @@ void wxSocketInternal::QueueRequest(SockRequest *request, bool async) wxThread::Yield(); } } - } else { m_request_locker.Lock(); diff --git a/src/common/socket.cpp b/src/common/socket.cpp index 47004a9dde..2372865175 100644 --- a/src/common/socket.cpp +++ b/src/common/socket.cpp @@ -209,8 +209,6 @@ wxSocketBase::~wxSocketBase() // First, close the file descriptor. Close(); - m_internal->FinalizeSocket(); - if (m_unread) free(m_unread); // Unregister from the handler database. @@ -228,8 +226,8 @@ bool wxSocketBase::Close() { if (m_fd != INVALID_SOCKET) { - // Pause all running socket thread. - m_internal->PauseSocket(); + if (m_notify_state == TRUE) + Notify(FALSE); // Shutdown the connection. shutdown(m_fd, 2); @@ -547,7 +545,7 @@ void wxSocketBase::SetNotify(wxRequestNotify flags) m_neededreq = flags; if (m_neededreq == 0) - m_internal->DisableWaiter(); + m_internal->StopWaiter(); else Notify(m_notify_state); } @@ -559,9 +557,9 @@ void wxSocketBase::Notify(bool notify) return; if (notify) - m_internal->EnableWaiter(); + m_internal->ResumeWaiter(); else - m_internal->DisableWaiter(); + m_internal->StopWaiter(); } void wxSocketBase::OnRequest(wxRequestEvent req_evt) @@ -577,7 +575,7 @@ void wxSocketBase::OnRequest(wxRequestEvent req_evt) // OldOnNotify(req_evt); // We disable the event reporting. - SetNotify(m_neededreq & ~notify); + m_neededreq &= ~notify; } } @@ -682,7 +680,7 @@ void wxSocketBase::WantBuffer(char *buffer, size_t nbytes, SockRequest *buf = new SockRequest; SaveState(); - m_internal->DisableWaiter(); + m_internal->StopWaiter(); buf->buffer = buffer; buf->size = nbytes; buf->done = FALSE; @@ -738,7 +736,7 @@ wxSocketServer::wxSocketServer(wxSockAddress& addr_man, return; } - m_internal->InitializeSocket(); + Notify(TRUE); } // -------------------------------------------------------------- @@ -769,7 +767,7 @@ bool wxSocketServer::AcceptWith(wxSocketBase& sock) sock.m_fd = fd2; sock.m_connected = TRUE; - sock.m_internal->InitializeSocket(); + sock.m_internal->ResumeWaiter(); return TRUE; } @@ -851,10 +849,6 @@ bool wxSocketClient::Connect(wxSockAddress& addr_man, bool WXUNUSED(wait) ) if (connect(m_fd, remote, len) != 0) return FALSE; - // Initializes the background threads ... - // -------------------------------------- - m_internal->InitializeSocket(); - // Enables bg events. // ------------------ Notify(TRUE); @@ -879,11 +873,10 @@ void wxSocketClient::OnRequest(wxRequestEvent evt) { if (m_connected) { - SetNotify(m_neededreq & ~REQ_CONNECT); + m_neededreq &= ~REQ_CONNECT; return; } m_connected = TRUE; - OldOnNotify(EVT_CONNECT); return; } wxSocketBase::OnRequest(evt); diff --git a/src/unix/threadpsx.cpp b/src/unix/threadpsx.cpp index d7dac9c864..ca1c7731b6 100644 --- a/src/unix/threadpsx.cpp +++ b/src/unix/threadpsx.cpp @@ -675,10 +675,10 @@ void wxThread::Exit(void *status) // next wake up the threads waiting for us (OTOH, this function won't return // until someone waited for us!) - p_internal->SignalExit(); - p_internal->SetState(STATE_EXITED); + p_internal->SignalExit(); + // delete both C++ thread object and terminate the OS thread object // GL: This is very ugly and buggy ... // delete this; -- 2.45.2