X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7d10ec93c4b0c4db9d4450bc39c6c127bfab57fe..6f026b5b63fe7ccb025e84509886f74772b9df13:/src/unix/appunix.cpp diff --git a/src/unix/appunix.cpp b/src/unix/appunix.cpp index 0bca1979a9..62f0c79ec9 100644 --- a/src/unix/appunix.cpp +++ b/src/unix/appunix.cpp @@ -1,20 +1,89 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: wx/unix/appunix.cpp +// Name: src/unix/appunix.cpp // Purpose: wxAppConsole with wxMainLoop implementation // Author: Lukasz Michalski // Created: 28/01/2005 -// RCS-ID: $Id$ // Copyright: (c) Lukasz Michalski // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#include "wx/app.h" -#include "wx/log.h" +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/app.h" + #include "wx/log.h" +#endif + #include "wx/evtloop.h" +#include "wx/scopedptr.h" +#include "wx/unix/private/wakeuppipe.h" +#include "wx/private/fdiodispatcher.h" +#include "wx/private/fdioeventloopsourcehandler.h" #include #include +#ifndef SA_RESTART + // don't use for systems which don't define it (at least VMS and QNX) + #define SA_RESTART 0 +#endif + +// ---------------------------------------------------------------------------- +// Helper class calling CheckSignal() on wake up +// ---------------------------------------------------------------------------- + +namespace +{ + +class SignalsWakeUpPipe : public wxWakeUpPipe +{ +public: + // Ctor automatically registers this pipe with the event loop. + SignalsWakeUpPipe() + { + m_source = wxEventLoopBase::AddSourceForFD + ( + GetReadFd(), + this, + wxEVENT_SOURCE_INPUT + ); + } + + virtual void OnReadWaiting() + { + // The base class wxWakeUpPipe::OnReadWaiting() needs to be called in order + // to read the data out of the wake up pipe and clear it for next time. + wxWakeUpPipe::OnReadWaiting(); + + if ( wxTheApp ) + wxTheApp->CheckSignal(); + } + + virtual ~SignalsWakeUpPipe() + { + delete m_source; + } + +private: + wxEventLoopSource* m_source; +}; + +} // anonymous namespace + +wxAppConsole::wxAppConsole() +{ + m_signalWakeUpPipe = NULL; +} + +wxAppConsole::~wxAppConsole() +{ + delete m_signalWakeUpPipe; +} + // use unusual names for arg[cv] to avoid clashes with wxApp members with the // same names bool wxAppConsole::Initialize(int& argc_, wxChar** argv_) @@ -27,14 +96,23 @@ bool wxAppConsole::Initialize(int& argc_, wxChar** argv_) return true; } +// The actual signal handler. It does as little as possible (because very few +// things are safe to do from inside a signal handler) and just ensures that +// CheckSignal() will be called later from SignalsWakeUpPipe::OnReadWaiting(). void wxAppConsole::HandleSignal(int signal) { wxAppConsole * const app = wxTheApp; if ( !app ) return; + // Register the signal that is caught. sigaddset(&(app->m_signalsCaught), signal); - app->WakeUpIdle(); + + // Wake up the application for handling the signal. + // + // Notice that we must have a valid wake up pipe here as we only install + // our signal handlers after allocating it. + app->m_signalWakeUpPipe->WakeUpNoLock(); } void wxAppConsole::CheckSignal() @@ -52,6 +130,27 @@ void wxAppConsole::CheckSignal() } } +wxFDIOHandler* wxAppConsole::RegisterSignalWakeUpPipe(wxFDIODispatcher& dispatcher) +{ + wxCHECK_MSG( m_signalWakeUpPipe, NULL, "Should be allocated" ); + + // we need a bridge to wxFDIODispatcher + // + // TODO: refactor the code so that only wxEventLoopSourceHandler is used + wxScopedPtr + fdioHandler(new wxFDIOEventLoopSourceHandler(m_signalWakeUpPipe)); + + if ( !dispatcher.RegisterFD + ( + m_signalWakeUpPipe->GetReadFd(), + fdioHandler.get(), + wxFDIO_INPUT + ) ) + return NULL; + + return fdioHandler.release(); +} + // the type of the signal handlers we use is "void(*)(int)" while the real // signal handlers are extern "C" and so have incompatible type and at least // Sun CC warns about it, so use explicit casts to suppress these warnings as @@ -66,6 +165,13 @@ bool wxAppConsole::SetSignalHandler(int signal, SignalHandler handler) const bool install = (SignalHandler_t)handler != SIG_DFL && (SignalHandler_t)handler != SIG_IGN; + if ( !m_signalWakeUpPipe ) + { + // Create the pipe that the signal handler will use to cause the event + // loop to call wxAppConsole::CheckSignal(). + m_signalWakeUpPipe = new SignalsWakeUpPipe(); + } + struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = (SignalHandler_t)&wxAppConsole::HandleSignal;