~ubuntu-branches/ubuntu/quantal/psi/quantal

« back to all changes in this revision

Viewing changes to iris/irisnet/processquit.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2009-09-25 17:49:51 UTC
  • mfrom: (6.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090925174951-lvm7kdap82o8xhn3
Tags: 0.13-1
* Updated to upstream version 0.13
* Set Standards-Version to 3.8.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2006  Justin Karneges
3
 
 *
4
 
 * This library is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Lesser General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2.1 of the License, or (at your option) any later version.
8
 
 *
9
 
 * This library is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
 * Lesser General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU Lesser General Public
15
 
 * License along with this library; if not, write to the Free Software
16
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
 
 * 02110-1301  USA
18
 
 *
19
 
 */
20
 
 
21
 
#include "processquit.h"
22
 
 
23
 
#ifndef NO_IRISNET
24
 
# include "irisnetglobal_p.h"
25
 
#endif
26
 
 
27
 
#ifdef QT_GUI_LIB
28
 
# include <QApplication>
29
 
#endif
30
 
 
31
 
#ifdef Q_OS_WIN
32
 
# include <windows.h>
33
 
#endif
34
 
 
35
 
#ifdef Q_OS_UNIX
36
 
# include <signal.h>
37
 
# include <unistd.h>
38
 
#endif
39
 
 
40
 
#ifndef NO_IRISNET
41
 
namespace XMPP {
42
 
#endif
43
 
 
44
 
Q_GLOBAL_STATIC(QMutex, pq_mutex)
45
 
static ProcessQuit *g_pq = 0;
46
 
 
47
 
inline bool is_gui_app()
48
 
{
49
 
#ifdef QT_GUI_LIB
50
 
        return (QApplication::type() != QApplication::Tty);
51
 
#else
52
 
        return false;
53
 
#endif
54
 
}
55
 
 
56
 
class ProcessQuit::Private : public QObject
57
 
{
58
 
        Q_OBJECT
59
 
public:
60
 
        ProcessQuit *q;
61
 
 
62
 
        bool done;
63
 
#ifdef Q_OS_WIN
64
 
        bool use_handler;
65
 
#endif
66
 
#ifdef Q_OS_UNIX
67
 
        int sig_pipe[2];
68
 
        QSocketNotifier *sig_notifier;
69
 
#endif
70
 
 
71
 
        Private(ProcessQuit *_q) : QObject(_q), q(_q)
72
 
        {
73
 
                done = false;
74
 
#ifdef Q_OS_WIN
75
 
                use_handler = !is_gui_app();
76
 
                if(use_handler)
77
 
                        SetConsoleCtrlHandler((PHANDLER_ROUTINE)winHandler, TRUE);
78
 
#endif
79
 
#ifdef Q_OS_UNIX
80
 
                pipe(sig_pipe);
81
 
                sig_notifier = new QSocketNotifier(sig_pipe[0], QSocketNotifier::Read, this);
82
 
                connect(sig_notifier, SIGNAL(activated(int)), SLOT(sig_activated(int)));
83
 
                unixWatchAdd(SIGINT);
84
 
                unixWatchAdd(SIGHUP);
85
 
                unixWatchAdd(SIGTERM);
86
 
#endif
87
 
        }
88
 
 
89
 
        ~Private()
90
 
        {
91
 
#ifdef Q_OS_WIN
92
 
                if(use_handler)
93
 
                        SetConsoleCtrlHandler((PHANDLER_ROUTINE)winHandler, FALSE);
94
 
#endif
95
 
#ifdef Q_OS_UNIX
96
 
                unixWatchRemove(SIGINT);
97
 
                unixWatchRemove(SIGHUP);
98
 
                unixWatchRemove(SIGTERM);
99
 
                delete sig_notifier;
100
 
                close(sig_pipe[0]);
101
 
                close(sig_pipe[1]);
102
 
#endif
103
 
        }
104
 
 
105
 
#ifdef Q_OS_WIN
106
 
        static BOOL winHandler(DWORD ctrlType)
107
 
        {
108
 
                Q_UNUSED(ctrlType);
109
 
                QMetaObject::invokeMethod(g_pq->d, "ctrl_ready", Qt::QueuedConnection);
110
 
                return TRUE;
111
 
        }
112
 
#endif
113
 
 
114
 
#ifdef Q_OS_UNIX
115
 
        static void unixHandler(int sig)
116
 
        {
117
 
                Q_UNUSED(sig);
118
 
                unsigned char c = 0;
119
 
                ::write(g_pq->d->sig_pipe[1], &c, 1);
120
 
        }
121
 
 
122
 
        void unixWatchAdd(int sig)
123
 
        {
124
 
                struct sigaction sa;
125
 
                sigaction(sig, NULL, &sa);
126
 
                // if the signal is ignored, don't take it over.  this is
127
 
                //   recommended by the glibc manual
128
 
                if(sa.sa_handler == SIG_IGN)
129
 
                        return;
130
 
                sigemptyset(&(sa.sa_mask));
131
 
                sa.sa_flags = 0;
132
 
                sa.sa_handler = unixHandler;
133
 
                sigaction(sig, &sa, 0);
134
 
        }
135
 
 
136
 
        void unixWatchRemove(int sig)
137
 
        {
138
 
                struct sigaction sa;
139
 
                sigaction(sig, NULL, &sa);
140
 
                // ignored means we skipped it earlier, so we should
141
 
                //   skip it again
142
 
                if(sa.sa_handler == SIG_IGN)
143
 
                        return;
144
 
                sigemptyset(&(sa.sa_mask));
145
 
                sa.sa_flags = 0;
146
 
                sa.sa_handler = SIG_DFL;
147
 
                sigaction(sig, &sa, 0);
148
 
        }
149
 
#endif
150
 
 
151
 
public slots:
152
 
        void ctrl_ready()
153
 
        {
154
 
#ifdef Q_OS_WIN
155
 
                do_emit();
156
 
#endif
157
 
        }
158
 
 
159
 
        void sig_activated(int)
160
 
        {
161
 
#ifdef Q_OS_UNIX
162
 
                unsigned char c;
163
 
                ::read(sig_pipe[0], &c, 1);
164
 
                do_emit();
165
 
#endif
166
 
        }
167
 
 
168
 
private:
169
 
        void do_emit()
170
 
        {
171
 
                // only signal once
172
 
                if(!done)
173
 
                {
174
 
                        done = true;
175
 
                        emit q->quit();
176
 
                }
177
 
        }
178
 
};
179
 
 
180
 
ProcessQuit::ProcessQuit(QObject *parent)
181
 
:QObject(parent)
182
 
{
183
 
        d = new Private(this);
184
 
}
185
 
 
186
 
ProcessQuit::~ProcessQuit()
187
 
{
188
 
        delete d;
189
 
}
190
 
 
191
 
ProcessQuit *ProcessQuit::instance()
192
 
{
193
 
        QMutexLocker locker(pq_mutex());
194
 
        if(!g_pq)
195
 
        {
196
 
                g_pq = new ProcessQuit;
197
 
                g_pq->moveToThread(QCoreApplication::instance()->thread());
198
 
#ifndef NO_IRISNET
199
 
                irisNetAddPostRoutine(cleanup);
200
 
#endif
201
 
        }
202
 
        return g_pq;
203
 
}
204
 
 
205
 
void ProcessQuit::reset()
206
 
{
207
 
        QMutexLocker locker(pq_mutex());
208
 
        if(g_pq)
209
 
                g_pq->d->done = false;
210
 
}
211
 
 
212
 
void ProcessQuit::cleanup()
213
 
{
214
 
        delete g_pq;
215
 
        g_pq = 0;
216
 
}
217
 
 
218
 
#ifndef NO_IRISNET
219
 
}
220
 
#endif
221
 
 
222
 
#include "processquit.moc"