1/*
2* Disktest
3* Copyright (c) International Business Machines Corp., 2005
4*
5* This program is free software; you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation; either version 2 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program; if not, write to the Free Software
17* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18*
19*  Please send e-mail to yardleyb@us.ibm.com if you have
20*  questions or comments.
21*
22*  Project Website:  TBD
23*
24* $Id: signals.c,v 1.1 2008/02/14 08:22:23 subrata_modak Exp $
25*/
26#ifdef WINDOWS
27#include <windows.h>
28#else
29#include <pthread.h>
30#endif
31#include <signal.h>
32#include "threading.h"
33#include "signals.h"
34
35/*
36 * global variable used to indicate what signal
37 * (if any) has been caught
38 */
39int handled_signal = -1;
40int signal_action = SIGNAL_NONE;
41
42/*
43 * mutex to be used whenever accessing the above
44 * global data
45 */
46#ifdef WINDOWS
47HANDLE sig_mutex;
48#else
49pthread_mutex_t sig_mutex = PTHREAD_MUTEX_INITIALIZER;
50#endif
51
52#ifdef WINDOWS
53void sig_handler(int sig)
54#else
55void *sig_handler(void *arg)
56#endif
57{
58#ifndef WINDOWS
59	sigset_t signal_set;
60	int sig;
61	int rv;
62
63	/* wait for any and all signals */
64	sigfillset(&signal_set);
65#ifdef AIX
66	/* except in AIX, can't sigwait on this signals */
67	sigdelset(&signal_set, SIGKILL);
68	sigdelset(&signal_set, SIGWAITING);
69	sigdelset(&signal_set, SIGSTOP);
70#endif
71
72	for (;;) {
73		rv = sigwait(&signal_set, &sig);
74#endif
75
76		switch (sig) {
77		case SIGQUIT:
78			LOCK(sig_mutex);
79			handled_signal = SIGQUIT;
80			signal_action |= SIGNAL_STOP;
81			UNLOCK(sig_mutex);
82			break;
83
84		case SIGINT:
85			LOCK(sig_mutex);
86			handled_signal = SIGINT;
87			signal_action |= SIGNAL_STOP;
88			UNLOCK(sig_mutex);
89			break;
90
91		case SIGTERM:
92			LOCK(sig_mutex);
93			handled_signal = SIGTERM;
94			signal_action |= SIGNAL_STOP;
95			UNLOCK(sig_mutex);
96			break;
97
98		case SIGHUP:
99			LOCK(sig_mutex);
100			handled_signal = SIGHUP;
101			signal_action |= SIGNAL_STOP;
102			UNLOCK(sig_mutex);
103			break;
104
105		case SIGUSR1:
106			LOCK(sig_mutex);
107			handled_signal = SIGUSR1;
108			signal_action |= SIGNAL_STAT;
109			UNLOCK(sig_mutex);
110			break;
111
112			/* whatever you need to do for other signals */
113		default:
114			LOCK(sig_mutex);
115			handled_signal = 0;
116			UNLOCK(sig_mutex);
117			break;
118		}
119#ifndef WINDOWS
120	}
121	return NULL;
122#endif
123}
124
125void setup_sig_mask(void)
126{
127#ifndef WINDOWS
128	sigset_t signal_set;
129	pthread_t sig_thread;
130#endif
131
132#ifdef WINDOWS
133	if ((sig_mutex = CreateMutex(NULL, FALSE, NULL)) == NULL) {
134		return;
135	}
136#endif
137
138	/* block all signals */
139#ifdef WINDOWS
140	signal(SIGINT, sig_handler);
141	signal(SIGTERM, sig_handler);
142	signal(SIGUSR1, sig_handler);
143#else
144	sigemptyset(&signal_set);
145	sigaddset(&signal_set, SIGINT);
146	sigaddset(&signal_set, SIGHUP);
147	sigaddset(&signal_set, SIGQUIT);
148	sigaddset(&signal_set, SIGTERM);
149	sigaddset(&signal_set, SIGUSR1);
150
151#ifdef AIX
152	sigthreadmask(SIG_SETMASK, &signal_set, NULL);
153#else
154	pthread_sigmask(SIG_SETMASK, &signal_set, NULL);
155#endif
156
157	/* create the signal handling thread */
158	pthread_create(&sig_thread, NULL, sig_handler, NULL);
159#endif
160}
161
162void clear_stat_signal(void)
163{
164	if (signal_action & SIGNAL_STAT) {
165		LOCK(sig_mutex);
166		signal_action &= ~SIGNAL_STAT;
167		UNLOCK(sig_mutex);
168	}
169}
170