/////////////////////////////////////////////////////////////////////////////
-// 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
/////////////////////////////////////////////////////////////////////////////
#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 <signal.h>
#include <unistd.h>
#ifndef SA_RESTART
// don't use for systems which don't define it (at least VMS and QNX)
- #define SA_RESTART
+ #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_)
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()
}
}
+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<wxFDIOHandler>
+ 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
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;