//Ensure that sigset_t is being defined
#include <signal.h>
+class wxFDIODispatcher;
+class wxFDIOHandler;
+class wxWakeUpPipe;
+
// wxApp subclass implementing event processing for console applications
class WXDLLIMPEXP_BASE wxAppConsole : public wxAppConsoleBase
{
public:
+ wxAppConsole();
+ virtual ~wxAppConsole();
+
// override base class initialization
virtual bool Initialize(int& argc, wxChar** argv);
// handlers for them
void CheckSignal();
+ // Register the signal wake up pipe with the given dispatcher.
+ //
+ // This is not used anywhere yet but will be soon.
+ //
+ // The pointer to the handler used for processing events on this descriptor
+ // is returned so that it can be deleted when we no longer needed it.
+ wxFDIOHandler* RegisterSignalWakeUpPipe(wxFDIODispatcher& dispatcher);
+
private:
// signal handler set up by SetSignalHandler() for all signals we handle,
// it just adds the signal to m_signalsCaught -- the real processing is
// the signal handlers
WX_DECLARE_HASH_MAP(int, SignalHandler, wxIntegerHash, wxIntegerEqual, SignalHandlerHash);
SignalHandlerHash m_signalHandlerHash;
+
+ // pipe used for wake up signal handling: if a signal arrives while we're
+ // blocking for input, writing to this pipe triggers a call to our CheckSignal()
+ wxWakeUpPipe *m_signalWakeUpPipe;
};
#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>
#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, false, "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;