ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/signal.C
Revision: 1.6
Committed: Sun Sep 16 18:54:45 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +7 -2 lines
Log Message:
#defines to enum

File Contents

# Content
1 /*
2 * signal.C: Signal-handling routines.
3 *
4 * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
5 * Rights to this code are as documented in COPYING.
6 *
7 *
8 * Portions of this file were derived from sources bearing the following license:
9 * Rights to this code are documented in doc/pod/license.pod.
10 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
11 */
12
13 static char const rcsid[] = "$Id: signal.C,v 1.5 2007-08-30 19:56:26 pippijn Exp $";
14
15 #include "atheme.h"
16 #include <ermyth/database.h>
17 #include "uplink.h"
18 #include "internal.h"
19 #include "connection.h"
20
21 typedef void (*signal_handler_t) (int);
22
23 static signal_handler_t
24 signal_install_handler_full (int signum, signal_handler_t handler, int *sigtoblock, size_t sigtoblocksize)
25 {
26 struct sigaction action, old_action;
27 size_t i;
28
29 action.sa_handler = handler;
30 action.sa_flags = SA_RESTART;
31
32 sigemptyset (&action.sa_mask);
33
34 for (i = 0; i < sigtoblocksize; i++)
35 sigaddset (&action.sa_mask, sigtoblock[i]);
36
37 if (sigaction (signum, &action, &old_action) == -1)
38 {
39 slog (LG_DEBUG, "Failed to install signal handler for signal %d", signum);
40 return NULL;
41 }
42
43 return old_action.sa_handler;
44 }
45
46 /*
47 * A version of signal(2) that works more reliably across different
48 * platforms.
49 *
50 * It restarts interrupted system calls, does not reset the handler,
51 * and blocks the same signal from within the handler.
52 */
53 static signal_handler_t
54 signal_install_handler (int signum, signal_handler_t handler)
55 {
56 return signal_install_handler_full (signum, handler, NULL, 0);
57 }
58
59 static void
60 signal_empty_handler (int signum)
61 {
62 /* do nothing */
63 }
64
65 static void
66 signal_hup_handler (int signum)
67 {
68 /* rehash */
69 slog (LG_INFO, "sighandler(): got SIGHUP, rehashing %s", config_file);
70
71 wallops (_("Got SIGHUP; reloading \2%s\2."), config_file);
72
73 snoop ("UPDATE: \2%s\2", "system console");
74 wallops (_("Updating database by request of \2%s\2."), "system console");
75 expire_check (NULL);
76 backend->save ();
77
78 snoop ("REHASH: \2%s\2", "system console");
79 wallops (_("Rehashing \2%s\2 by request of \2%s\2."), config_file, "system console");
80
81 /* reload the config, opening other logs besides the core log if needed. */
82 if (!conf_rehash ())
83 wallops (_("REHASH of \2%s\2 failed. Please correct any errors in the file and try again."), config_file);
84
85 return;
86 }
87
88 static void
89 signal_int_handler (int signum)
90 {
91 /* usually caused by ^C */
92 if (runflags & RF_LIVE)
93 {
94 wallops (_("Exiting on signal %d."), SIGINT);
95 if (chansvs.me != NULL && chansvs.me->me != NULL)
96 phandler->quit_sts (chansvs.me->me, "caught interrupt");
97 me.connected = false;
98 slog (LG_INFO, "sighandler(): caught interrupt; exiting...");
99 runflags |= RF_SHUTDOWN;
100 }
101 else if (!(runflags & RF_LIVE))
102 {
103 wallops (_("Got SIGINT; restarting."));
104
105 snoop ("UPDATE: \2%s\2", "system console");
106 wallops (_("Updating database by request of \2%s\2."), "system console");
107 expire_check (NULL);
108 backend->save ();
109
110 snoop ("RESTART: \2%s\2", "system console");
111 wallops (_("Restarting by request of \2%s\2."), "system console");
112
113 slog (LG_INFO, "sighandler(): restarting...");
114 runflags |= RF_RESTART;
115 }
116 }
117
118 static void
119 signal_term_handler (int signum)
120 {
121 wallops (_("Exiting on signal %d."), SIGTERM);
122 slog (LG_INFO, "sighandler(): got SIGTERM; exiting...");
123 runflags |= RF_SHUTDOWN;
124 }
125
126 static void
127 signal_usr2_handler (int signum)
128 {
129 wallops (_("Got SIGUSR2; restarting."));
130
131 snoop ("UPDATE: \2%s\2", "system console");
132 wallops (_("Updating database by request of \2%s\2."), "system console");
133 expire_check (NULL);
134 backend->save ();
135
136 snoop ("RESTART: \2%s\2", "system console");
137 wallops (_("Restarting by request of \2%s\2."), "system console");
138
139 slog (LG_INFO, "sighandler(): restarting...");
140 runflags |= RF_RESTART;
141 }
142
143 /* XXX */
144 static void signal_usr1_handler (int signum) __attribute__ ((__noreturn__));
145 static void
146 signal_usr1_handler (int signum)
147 {
148 if (me.connected && curr_uplink != NULL && curr_uplink->conn != NULL)
149 {
150 if (chansvs.nick != NULL)
151 {
152 write (curr_uplink->conn->fd, ":", 1);
153 write (curr_uplink->conn->fd, chansvs.nick, strlen (chansvs.nick));
154 write (curr_uplink->conn->fd, " QUIT :Out of memory!\r\n", 23);
155 }
156 write (curr_uplink->conn->fd, "ERROR :Panic! Out of memory.\r\n", 30);
157 }
158 if (runflags & (RF_LIVE | RF_STARTING))
159 write (2, "Out of memory!\n", 15);
160 abort ();
161 }
162
163 void
164 init_signal_handlers (void)
165 {
166 signal_install_handler (SIGHUP, signal_hup_handler);
167 signal_install_handler (SIGINT, signal_int_handler);
168 signal_install_handler (SIGTERM, signal_term_handler);
169 signal_install_handler (SIGPIPE, signal_empty_handler);
170
171 signal_install_handler (SIGUSR1, signal_usr1_handler);
172 signal_install_handler (SIGUSR2, signal_usr2_handler);
173 }