X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b46b1d59d6f69ad80dcf5955375578a6504d100a..6ba718d7aee2f519d9146b90424ccec9e2243479:/src/unix/appunix.cpp diff --git a/src/unix/appunix.cpp b/src/unix/appunix.cpp index a40991715a..62f0c79ec9 100644 --- a/src/unix/appunix.cpp +++ b/src/unix/appunix.cpp @@ -1,26 +1,94 @@ ///////////////////////////////////////////////////////////////////////////// -// 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 -bool wxAppConsoleUnix::Initialize(int& argc, wxChar** argv) +#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 { - if ( !wxAppConsole::Initialize(argc,argv) ) - return false; - if ( !m_mainLoop->IsOk() ) +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_) +{ + if ( !wxAppConsoleBase::Initialize(argc_, argv_) ) return false; sigemptyset(&m_signalsCaught); @@ -28,17 +96,26 @@ bool wxAppConsoleUnix::Initialize(int& argc, wxChar** argv) return true; } -void wxAppConsoleUnix::HandleSignal(int signal) +// 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) { - wxAppConsoleUnix * const app = wxTheApp; + 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 wxAppConsoleUnix::CheckSignal() +void wxAppConsole::CheckSignal() { for ( SignalHandlerHash::iterator it = m_signalHandlerHash.begin(); it != m_signalHandlerHash.end(); @@ -53,13 +130,51 @@ void wxAppConsoleUnix::CheckSignal() } } -bool wxAppConsoleUnix::SetSignalHandler(int signal, SignalHandler handler) +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 +// they should be harmless +extern "C" +{ + typedef void (*SignalHandler_t)(int); +} + +bool wxAppConsole::SetSignalHandler(int signal, SignalHandler handler) { - const bool install = handler != SIG_DFL && handler != SIG_IGN; + 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 = &wxAppConsoleUnix::HandleSignal; + sa.sa_handler = (SignalHandler_t)&wxAppConsole::HandleSignal; sa.sa_flags = SA_RESTART; int res = sigaction(signal, &sa, 0); if ( res != 0 ) @@ -75,3 +190,4 @@ bool wxAppConsoleUnix::SetSignalHandler(int signal, SignalHandler handler) return true; } +