2011-03-20 18:05:19 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Name: src/unix/appunix.cpp
|
|
|
|
// Purpose: wxAppConsole with wxMainLoop implementation
|
|
|
|
// Author: Lukasz Michalski
|
|
|
|
// Created: 28/01/2005
|
|
|
|
// Copyright: (c) Lukasz Michalski
|
|
|
|
// Licence: wxWindows licence
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#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"
|
2013-09-22 18:44:55 -04:00
|
|
|
#include "wx/scopedptr.h"
|
|
|
|
#include "wx/unix/private/wakeuppipe.h"
|
|
|
|
#include "wx/private/fdiodispatcher.h"
|
|
|
|
#include "wx/private/fdioeventloopsourcehandler.h"
|
2011-03-20 18:05:19 +00:00
|
|
|
|
|
|
|
#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 0
|
|
|
|
#endif
|
|
|
|
|
2013-09-22 18:44:55 -04:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// 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
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-06-26 05:25:29 +00:00
|
|
|
virtual void OnReadWaiting() wxOVERRIDE
|
2013-09-22 18:44:55 -04:00
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2011-03-20 18:05:19 +00:00
|
|
|
// 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);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-09-22 18:44:55 -04:00
|
|
|
// 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().
|
2011-03-20 18:05:19 +00:00
|
|
|
void wxAppConsole::HandleSignal(int signal)
|
|
|
|
{
|
|
|
|
wxAppConsole * const app = wxTheApp;
|
|
|
|
if ( !app )
|
|
|
|
return;
|
|
|
|
|
2013-09-22 18:44:55 -04:00
|
|
|
// Register the signal that is caught.
|
2011-03-20 18:05:19 +00:00
|
|
|
sigaddset(&(app->m_signalsCaught), signal);
|
2013-09-22 18:44:55 -04:00
|
|
|
|
|
|
|
// 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();
|
2011-03-20 18:05:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void wxAppConsole::CheckSignal()
|
|
|
|
{
|
|
|
|
for ( SignalHandlerHash::iterator it = m_signalHandlerHash.begin();
|
|
|
|
it != m_signalHandlerHash.end();
|
|
|
|
++it )
|
|
|
|
{
|
|
|
|
int sig = it->first;
|
|
|
|
if ( sigismember(&m_signalsCaught, sig) )
|
|
|
|
{
|
|
|
|
sigdelset(&m_signalsCaught, sig);
|
|
|
|
(it->second)(sig);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-22 18:44:55 -04:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2011-03-20 18:05:19 +00:00
|
|
|
// 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 = (SignalHandler_t)handler != SIG_DFL &&
|
|
|
|
(SignalHandler_t)handler != SIG_IGN;
|
|
|
|
|
2013-09-22 18:44:55 -04:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2011-03-20 18:05:19 +00:00
|
|
|
struct sigaction sa;
|
|
|
|
memset(&sa, 0, sizeof(sa));
|
|
|
|
sa.sa_handler = (SignalHandler_t)&wxAppConsole::HandleSignal;
|
|
|
|
sa.sa_flags = SA_RESTART;
|
|
|
|
int res = sigaction(signal, &sa, 0);
|
|
|
|
if ( res != 0 )
|
|
|
|
{
|
|
|
|
wxLogSysError(_("Failed to install signal handler"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( install )
|
|
|
|
m_signalHandlerHash[signal] = handler;
|
|
|
|
else
|
|
|
|
m_signalHandlerHash.erase(signal);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|