13
13
along with this program; if not, write to the Free Software
14
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
#include <drizzled/server_includes.h>
17
17
#include <drizzled/gettext.h>
18
18
#include <drizzled/error.h>
19
19
#include <drizzled/unireg.h>
20
#include <drizzled/plugin/storage_engine.h>
21
#include <drizzled/cursor.h> /* for refresh_version */
22
#include "drizzled/pthread_globals.h"
23
#include "drizzled/internal/my_pthread.h"
24
#include "drizzled/internal/my_sys.h"
25
#include "drizzled/plugin/daemon.h"
26
#include "drizzled/signal_handler.h"
28
#include "drizzled/session/cache.h"
30
#include "drizzled/drizzled.h"
32
#include <boost/thread/thread.hpp>
33
#include <boost/filesystem.hpp>
39
21
static bool kill_in_progress= false;
40
void signal_hand(void);
22
static bool volatile signal_thread_in_use= false;
44
23
extern int cleanup_done;
45
extern bool volatile abort_loop;
46
extern bool volatile shutdown_in_progress;
47
extern boost::filesystem::path pid_file;
48
26
/* Prototypes -> all of these should be factored out into a propper shutdown */
49
extern void close_connections(void);
50
extern std::bitset<12> test_flags;
53
using namespace drizzled;
27
void close_connections(void);
28
bool reload_cache(Session *session, ulong options, TableList *tables);
66
39
or stop, we just want to kill the server.
69
static void kill_server(int sig)
42
static void kill_server(void *sig_ptr)
44
int sig=(int) (long) sig_ptr; // This is passed a int
71
45
// if there is a signal during the kill in progress, ignore the other
72
46
if (kill_in_progress) // Safety
74
48
kill_in_progress=true;
75
49
abort_loop=1; // This should be set
76
50
if (sig != 0) // 0 is not a valid signal number
77
ignore_signal(sig); /* purify inspected */
51
my_sigset(sig, SIG_IGN); /* purify inspected */
78
52
if (sig == SIGTERM || sig == 0)
79
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
53
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),my_progname);
81
errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
55
errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),my_progname,sig); /* purecov: inspected */
82
57
close_connections();
58
if (sig != SIGTERM && sig != 0)
59
unireg_abort(1); /* purecov: inspected */
105
84
(void)close(file); /* We can ignore the error, since we are going to error anyway at this point */
107
memset(buff, 0, sizeof(buff));
108
snprintf(buff, sizeof(buff)-1, "Can't start server: can't create PID file (%s)", pid_file.file_string().c_str());
86
snprintf(buff, 1024, "Can't start server: can't create PID file (%s)", pidfile_name);
114
92
/** This threads handles all signals and alarms. */
95
pthread_handler_t signal_hand(void *)
119
internal::my_thread_init(); // Init new thread
120
boost::this_thread::at_thread_exit(&internal::my_thread_end);
99
my_thread_init(); // Init new thread
121
100
signal_thread_in_use= true;
123
if ((test_flags.test(TEST_SIGINT)))
102
if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
125
104
(void) sigemptyset(&set); // Setup up SIGINT for debug
126
105
(void) sigaddset(&set,SIGINT); // For debugging
129
108
(void) sigemptyset(&set); // Setup up SIGINT for debug
130
109
#ifndef IGNORE_SIGHUP_SIGQUIT
131
if (sigaddset(&set,SIGQUIT))
133
std::cerr << "failed setting sigaddset() with SIGQUIT\n";
135
if (sigaddset(&set,SIGHUP))
137
std::cerr << "failed setting sigaddset() with SIGHUP\n";
110
(void) sigaddset(&set,SIGQUIT);
111
(void) sigaddset(&set,SIGHUP);
140
if (sigaddset(&set,SIGTERM))
142
std::cerr << "failed setting sigaddset() with SIGTERM\n";
144
if (sigaddset(&set,SIGTSTP))
146
std::cerr << "failed setting sigaddset() with SIGTSTP\n";
113
(void) sigaddset(&set,SIGTERM);
114
(void) sigaddset(&set,SIGTSTP);
149
116
/* Save pid to this process (or thread on Linux) */
150
117
create_pid_file();
119
#ifdef HAVE_STACK_TRACE_ON_SEGV
122
sprintf(pstack_file_name,"drizzled-%lu-%%d-%%d.backtrace", (uint32_t)getpid());
123
pstack_install_segv_action(pstack_file_name);
125
#endif /* HAVE_STACK_TRACE_ON_SEGV */
153
128
signal to init that we are ready
154
129
This works by waiting for init to free mutex,
161
136
(Asked MontyW over the phone about this.) -Brian
164
session::Cache::singleton().mutex().lock();
165
session::Cache::singleton().mutex().unlock();
166
COND_thread_count.notify_all();
168
if (pthread_sigmask(SIG_BLOCK, &set, NULL))
170
std::cerr << "Failed to set pthread_sigmask() in signal handler\n";
139
if (pthread_mutex_lock(&LOCK_thread_count) == 0)
140
(void) pthread_mutex_unlock(&LOCK_thread_count);
141
(void) pthread_cond_broadcast(&COND_thread_count);
143
(void) pthread_sigmask(SIG_BLOCK,&set,NULL);
175
146
int error; // Used when debugging
177
147
if (shutdown_in_progress && !abort_loop)
184
while ((error= sigwait(&set, &sig)) == EINTR) ;
153
while ((error= sigwait(&set,&sig)) == EINTR) ;
187
154
if (cleanup_done)
189
157
signal_thread_in_use= false;
198
165
/* switch to the old log message processing */
201
168
abort_loop=1; // mark abort for threads
202
kill_server(sig); // MIT THREAD has a alarm thread
169
kill_server((void*) sig); // MIT THREAD has a alarm thread
209
drizzled::plugin::StorageEngine::flushLogs(NULL);
174
reload_cache(NULL, (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST ), NULL); // Flush logs
177
break; /* purecov: tested */
183
static int init(PluginRegistry&)
186
pthread_attr_t thr_attr;
187
size_t my_thread_stack_size= 65536;
189
(void) pthread_attr_init(&thr_attr);
190
pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
191
(void) pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED);
193
struct sched_param tmp_sched_param;
195
memset(&tmp_sched_param, 0, sizeof(tmp_sched_param));
196
tmp_sched_param.sched_priority= INTERRUPT_PRIOR;
197
(void)pthread_attr_setschedparam(&thr_attr, &tmp_sched_param);
199
#if defined(__ia64__) || defined(__ia64)
201
Peculiar things with ia64 platforms - it seems we only have half the
202
stack size in reality, so we have to double it here
204
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size*2);
206
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size);
209
(void) pthread_mutex_lock(&LOCK_thread_count);
210
if ((error=pthread_create(&signal_thread, &thr_attr, signal_hand, 0)))
212
errmsg_printf(ERRMSG_LVL_ERROR, _("Can't create interrupt-thread (error %d, errno: %d)"),
216
(void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
217
pthread_mutex_unlock(&LOCK_thread_count);
219
(void) pthread_attr_destroy(&thr_attr);
225
This is mainly needed when running with purify, but it's still nice to
226
know that all child threads have died when drizzled exits.
228
static int deinit(PluginRegistry&)
232
Wait up to 10 seconds for signal thread to die. We use this mainly to
233
avoid getting warnings that my_thread_end has not been called
235
for (i= 0 ; i < 100 && signal_thread_in_use; i++)
237
if (pthread_kill(signal_thread, SIGTERM) != ESRCH)
218
class SignalHandler :
219
public drizzled::plugin::Daemon
221
SignalHandler(const SignalHandler &);
222
SignalHandler& operator=(const SignalHandler &);
223
boost::thread thread;
227
drizzled::plugin::Daemon("Signal Handler")
229
// @todo fix spurious wakeup issue
230
boost::mutex::scoped_lock scopedLock(session::Cache::singleton().mutex());
231
thread= boost::thread(signal_hand);
232
signal_thread= thread.native_handle();
233
COND_thread_count.wait(scopedLock);
237
This is mainly needed when running with purify, but it's still nice to
238
know that all child threads have died when drizzled exits.
243
Wait up to 100000 micro-seconds for signal thread to die. We use this mainly to
244
avoid getting warnings that internal::my_thread_end has not been called
246
bool completed= false;
248
* We send SIGTERM and then do a timed join. If that fails we will on
249
* the last pthread_kill() call SIGTSTP. OSX (and FreeBSD) seem to
250
* prefer this. -Brian
252
uint32_t count= 2; // How many times to try join and see if the caller died.
253
while (not completed and count--)
256
int signal= count == 1 ? SIGTSTP : SIGTERM;
258
if ((error= pthread_kill(thread.native_handle(), signal)))
260
char buffer[1024]; // No reason for number;
261
strerror_r(error, buffer, sizeof(buffer));
262
std::cerr << "pthread_kill() error on shutdown of signal thread (" << buffer << ")\n";
267
boost::posix_time::milliseconds duration(100);
268
completed= thread.timed_join(duration);
274
static int init(drizzled::module::Context& context)
276
context.add(new SignalHandler);
239
usleep(100); // Give it time to die
282
static drizzle_sys_var* system_variables[]= {
245
static struct st_mysql_sys_var* system_variables[]= {
286
DRIZZLE_DECLARE_PLUGIN
249
drizzle_declare_plugin(signal_handler)
289
251
"signal_handler",
292
254
"Default Signal Handler",
293
255
PLUGIN_LICENSE_GPL,
294
256
init, /* Plugin Init */
257
deinit, /* Plugin Deinit */
258
NULL, /* status variables */
295
259
system_variables, /* system variables */
296
260
NULL /* config options */
298
DRIZZLE_DECLARE_PLUGIN_END;
262
drizzle_declare_plugin_end;