]> git.saurik.com Git - wxWidgets.git/blame - src/unix/appunix.cpp
Don't ignore child process output if it exits with -1 exit code.
[wxWidgets.git] / src / unix / appunix.cpp
CommitLineData
b46b1d59 1/////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: src/unix/appunix.cpp
b46b1d59
VZ
3// Purpose: wxAppConsole with wxMainLoop implementation
4// Author: Lukasz Michalski
5// Created: 28/01/2005
6// RCS-ID: $Id$
7// Copyright: (c) Lukasz Michalski
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
74ab5f5b
VZ
11#include "wx/wxprec.h"
12
13#ifdef __BORLANDC__
14 #pragma hdrstop
15#endif
16
17#ifndef WX_PRECOMP
18 #include "wx/app.h"
19 #include "wx/log.h"
20#endif
21
b46b1d59 22#include "wx/evtloop.h"
d5ab427f
VZ
23#include "wx/scopedptr.h"
24#include "wx/unix/private/wakeuppipe.h"
25#include "wx/private/fdiodispatcher.h"
26#include "wx/private/fdioeventloopsourcehandler.h"
b46b1d59
VZ
27
28#include <signal.h>
29#include <unistd.h>
30
26844c72
VZ
31#ifndef SA_RESTART
32 // don't use for systems which don't define it (at least VMS and QNX)
e1cf09d9 33 #define SA_RESTART 0
26844c72
VZ
34#endif
35
d5ab427f
VZ
36// ----------------------------------------------------------------------------
37// Helper class calling CheckSignal() on wake up
38// ----------------------------------------------------------------------------
39
40namespace
41{
42
43class SignalsWakeUpPipe : public wxWakeUpPipe
44{
45public:
46 // Ctor automatically registers this pipe with the event loop.
47 SignalsWakeUpPipe()
48 {
49 m_source = wxEventLoopBase::AddSourceForFD
50 (
51 GetReadFd(),
52 this,
53 wxEVENT_SOURCE_INPUT
54 );
55 }
56
57 virtual void OnReadWaiting()
58 {
59 // The base class wxWakeUpPipe::OnReadWaiting() needs to be called in order
60 // to read the data out of the wake up pipe and clear it for next time.
61 wxWakeUpPipe::OnReadWaiting();
62
63 if ( wxTheApp )
64 wxTheApp->CheckSignal();
65 }
66
67 virtual ~SignalsWakeUpPipe()
68 {
69 delete m_source;
70 }
71
72private:
73 wxEventLoopSource* m_source;
74};
75
76} // anonymous namespace
77
78wxAppConsole::wxAppConsole()
79{
80 m_signalWakeUpPipe = NULL;
81}
82
83wxAppConsole::~wxAppConsole()
84{
85 delete m_signalWakeUpPipe;
86}
87
3bc8edd5
VZ
88// use unusual names for arg[cv] to avoid clashes with wxApp members with the
89// same names
90bool wxAppConsole::Initialize(int& argc_, wxChar** argv_)
b46b1d59 91{
3bc8edd5 92 if ( !wxAppConsoleBase::Initialize(argc_, argv_) )
b46b1d59
VZ
93 return false;
94
95 sigemptyset(&m_signalsCaught);
96
97 return true;
98}
99
d5ab427f
VZ
100// The actual signal handler. It does as little as possible (because very few
101// things are safe to do from inside a signal handler) and just ensures that
102// CheckSignal() will be called later from SignalsWakeUpPipe::OnReadWaiting().
e0954e72 103void wxAppConsole::HandleSignal(int signal)
b46b1d59 104{
e0954e72 105 wxAppConsole * const app = wxTheApp;
b46b1d59
VZ
106 if ( !app )
107 return;
108
d5ab427f 109 // Register the signal that is caught.
b46b1d59 110 sigaddset(&(app->m_signalsCaught), signal);
d5ab427f
VZ
111
112 // Wake up the application for handling the signal.
113 //
114 // Notice that we must have a valid wake up pipe here as we only install
115 // our signal handlers after allocating it.
116 app->m_signalWakeUpPipe->WakeUpNoLock();
b46b1d59
VZ
117}
118
e0954e72 119void wxAppConsole::CheckSignal()
b46b1d59
VZ
120{
121 for ( SignalHandlerHash::iterator it = m_signalHandlerHash.begin();
122 it != m_signalHandlerHash.end();
123 ++it )
124 {
125 int sig = it->first;
126 if ( sigismember(&m_signalsCaught, sig) )
127 {
128 sigdelset(&m_signalsCaught, sig);
129 (it->second)(sig);
130 }
131 }
132}
133
d5ab427f
VZ
134wxFDIOHandler* wxAppConsole::RegisterSignalWakeUpPipe(wxFDIODispatcher& dispatcher)
135{
136 wxCHECK_MSG( m_signalWakeUpPipe, false, "Should be allocated" );
137
138 // we need a bridge to wxFDIODispatcher
139 //
140 // TODO: refactor the code so that only wxEventLoopSourceHandler is used
141 wxScopedPtr<wxFDIOHandler>
142 fdioHandler(new wxFDIOEventLoopSourceHandler(m_signalWakeUpPipe));
143
144 if ( !dispatcher.RegisterFD
145 (
146 m_signalWakeUpPipe->GetReadFd(),
147 fdioHandler.get(),
148 wxFDIO_INPUT
149 ) )
150 return NULL;
151
152 return fdioHandler.release();
153}
154
7d10ec93
VZ
155// the type of the signal handlers we use is "void(*)(int)" while the real
156// signal handlers are extern "C" and so have incompatible type and at least
157// Sun CC warns about it, so use explicit casts to suppress these warnings as
158// they should be harmless
159extern "C"
160{
161 typedef void (*SignalHandler_t)(int);
162}
163
e0954e72 164bool wxAppConsole::SetSignalHandler(int signal, SignalHandler handler)
b46b1d59 165{
7d10ec93
VZ
166 const bool install = (SignalHandler_t)handler != SIG_DFL &&
167 (SignalHandler_t)handler != SIG_IGN;
b46b1d59 168
d5ab427f
VZ
169 if ( !m_signalWakeUpPipe )
170 {
171 // Create the pipe that the signal handler will use to cause the event
172 // loop to call wxAppConsole::CheckSignal().
173 m_signalWakeUpPipe = new SignalsWakeUpPipe();
174 }
175
b46b1d59
VZ
176 struct sigaction sa;
177 memset(&sa, 0, sizeof(sa));
7d10ec93 178 sa.sa_handler = (SignalHandler_t)&wxAppConsole::HandleSignal;
26844c72
VZ
179 sa.sa_flags = SA_RESTART;
180 int res = sigaction(signal, &sa, 0);
b46b1d59
VZ
181 if ( res != 0 )
182 {
183 wxLogSysError(_("Failed to install signal handler"));
184 return false;
185 }
186
187 if ( install )
188 m_signalHandlerHash[signal] = handler;
189 else
190 m_signalHandlerHash.erase(signal);
191
192 return true;
193}
f6342fb5 194