15
13
along with this program; if not, write to the Free Software
16
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
20
17
#include <drizzled/gettext.h>
21
18
#include <drizzled/error.h>
22
19
#include <drizzled/unireg.h>
23
20
#include <drizzled/plugin/storage_engine.h>
24
#include <drizzled/pthread_globals.h>
25
#include <drizzled/internal/my_pthread.h>
26
#include <drizzled/internal/my_sys.h>
27
#include <drizzled/plugin/daemon.h>
28
#include <drizzled/signal_handler.h>
30
#include <drizzled/session.h>
31
#include <drizzled/session/cache.h>
33
#include <drizzled/debug.h>
35
#include <drizzled/drizzled.h>
37
#include <drizzled/refresh_version.h>
39
#include <boost/thread/thread.hpp>
40
#include <boost/filesystem.hpp>
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"
42
26
#include <sys/stat.h>
46
30
static bool kill_in_progress= false;
47
void signal_hand(void);
31
static bool volatile signal_thread_in_use= false;
32
extern "C" pthread_handler_t signal_hand(void *);
51
36
extern int cleanup_done;
52
37
extern bool volatile abort_loop;
53
38
extern bool volatile shutdown_in_progress;
54
extern boost::filesystem::path pid_file;
39
extern char pidfile_name[FN_REFLEN];
55
40
/* Prototypes -> all of these should be factored out into a propper shutdown */
56
41
extern void close_connections(void);
42
extern std::bitset<12> test_flags;
59
45
using namespace drizzled;
65
50
Force server down. Kill all connections and threads and exit.
72
57
or stop, we just want to kill the server.
75
static void kill_server(int sig)
60
static void kill_server(void *sig_ptr)
62
int sig=(int) (long) sig_ptr; // This is passed a int
77
63
// if there is a signal during the kill in progress, ignore the other
78
64
if (kill_in_progress) // Safety
80
66
kill_in_progress=true;
81
67
abort_loop=1; // This should be set
82
68
if (sig != 0) // 0 is not a valid signal number
83
ignore_signal(sig); /* purify inspected */
69
my_sigset(sig, SIG_IGN); /* purify inspected */
84
70
if (sig == SIGTERM || sig == 0)
85
errmsg_printf(error::INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
71
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
87
errmsg_printf(error::ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
73
errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
89
75
close_connections();
76
if (sig != SIGTERM && sig != 0)
112
102
(void)close(file); /* We can ignore the error, since we are going to error anyway at this point */
114
memset(buff, 0, sizeof(buff));
115
snprintf(buff, sizeof(buff)-1, "Can't start server: can't create PID file (%s)", pid_file.file_string().c_str());
104
snprintf(buff, 1024, "Can't start server: can't create PID file (%s)", pidfile_name);
116
105
sql_perror(buff);
121
110
/** This threads handles all signals and alarms. */
111
pthread_handler_t signal_hand(void *)
126
115
internal::my_thread_init(); // Init new thread
127
boost::this_thread::at_thread_exit(&internal::my_thread_end);
128
116
signal_thread_in_use= true;
130
if ((drizzled::getDebug().test(drizzled::debug::ALLOW_SIGINT)))
118
if (internal::thd_lib_detected != THD_LIB_LT &&
119
(test_flags.test(TEST_SIGINT)))
132
121
(void) sigemptyset(&set); // Setup up SIGINT for debug
133
122
(void) sigaddset(&set,SIGINT); // For debugging
134
(void) pthread_sigmask(SIG_UNBLOCK, &set, NULL);
123
(void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
136
125
(void) sigemptyset(&set); // Setup up SIGINT for debug
137
126
#ifndef IGNORE_SIGHUP_SIGQUIT
138
if (sigaddset(&set,SIGQUIT))
140
std::cerr << "failed setting sigaddset() with SIGQUIT\n";
142
if (sigaddset(&set,SIGHUP))
144
std::cerr << "failed setting sigaddset() with SIGHUP\n";
127
(void) sigaddset(&set,SIGQUIT);
128
(void) sigaddset(&set,SIGHUP);
147
if (sigaddset(&set,SIGTERM))
149
std::cerr << "failed setting sigaddset() with SIGTERM\n";
151
if (sigaddset(&set,SIGTSTP))
153
std::cerr << "failed setting sigaddset() with SIGTSTP\n";
130
(void) sigaddset(&set,SIGTERM);
131
(void) sigaddset(&set,SIGTSTP);
156
133
/* Save pid to this process (or thread on Linux) */
157
134
create_pid_file();
136
#ifdef HAVE_STACK_TRACE_ON_SEGV
139
sprintf(pstack_file_name,"drizzled-%lu-%%d-%%d.backtrace", (uint32_t)getpid());
140
pstack_install_segv_action(pstack_file_name);
142
#endif /* HAVE_STACK_TRACE_ON_SEGV */
160
145
signal to init that we are ready
161
146
This works by waiting for init to free mutex,
168
153
(Asked MontyW over the phone about this.) -Brian
171
session::Cache::singleton().mutex().lock();
172
session::Cache::singleton().mutex().unlock();
173
COND_thread_count.notify_all();
175
if (pthread_sigmask(SIG_BLOCK, &set, NULL))
177
std::cerr << "Failed to set pthread_sigmask() in signal handler\n";
156
if (pthread_mutex_lock(&LOCK_thread_count) == 0)
157
(void) pthread_mutex_unlock(&LOCK_thread_count);
158
(void) pthread_cond_broadcast(&COND_thread_count);
160
(void) pthread_sigmask(SIG_BLOCK,&set,NULL);
182
163
int error; // Used when debugging
184
164
if (shutdown_in_progress && !abort_loop)
191
while ((error= sigwait(&set, &sig)) == EINTR) ;
170
while ((error= sigwait(&set,&sig)) == EINTR) ;
194
171
if (cleanup_done)
173
internal::my_thread_end();
196
174
signal_thread_in_use= false;
205
182
/* switch to the old log message processing */
208
185
abort_loop=1; // mark abort for threads
209
kill_server(sig); // MIT THREAD has a alarm thread
186
kill_server((void*) sig); // MIT THREAD has a alarm thread
225
class SignalHandler :
226
public drizzled::plugin::Daemon
228
SignalHandler(const SignalHandler &);
229
SignalHandler& operator=(const SignalHandler &);
230
boost::thread thread;
234
drizzled::plugin::Daemon("Signal Handler")
236
// @todo fix spurious wakeup issue
237
boost::mutex::scoped_lock scopedLock(session::Cache::singleton().mutex());
238
thread= boost::thread(signal_hand);
239
signal_thread= thread.native_handle();
240
COND_thread_count.wait(scopedLock);
244
This is mainly needed when running with purify, but it's still nice to
245
know that all child threads have died when drizzled exits.
250
Wait up to 100000 micro-seconds for signal thread to die. We use this mainly to
251
avoid getting warnings that internal::my_thread_end has not been called
253
bool completed= false;
255
* We send SIGTERM and then do a timed join. If that fails we will on
256
* the last pthread_kill() call SIGTSTP. OSX (and FreeBSD) seem to
257
* prefer this. -Brian
259
uint32_t count= 2; // How many times to try join and see if the caller died.
260
while (not completed and count--)
263
int signal= count == 1 ? SIGTSTP : SIGTERM;
265
if ((error= pthread_kill(thread.native_handle(), signal)))
267
char buffer[1024]; // No reason for number;
268
strerror_r(error, buffer, sizeof(buffer));
269
std::cerr << "pthread_kill() error on shutdown of signal thread (" << buffer << ")\n";
274
boost::posix_time::milliseconds duration(100);
275
completed= thread.timed_join(duration);
203
static int init(drizzled::plugin::Registry&)
206
pthread_attr_t thr_attr;
207
size_t my_thread_stack_size= 65536;
209
(void) pthread_attr_init(&thr_attr);
210
pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
211
(void) pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED);
213
struct sched_param tmp_sched_param;
215
memset(&tmp_sched_param, 0, sizeof(tmp_sched_param));
216
tmp_sched_param.sched_priority= INTERRUPT_PRIOR;
217
(void)pthread_attr_setschedparam(&thr_attr, &tmp_sched_param);
219
#if defined(__ia64__) || defined(__ia64)
221
Peculiar things with ia64 platforms - it seems we only have half the
222
stack size in reality, so we have to double it here
224
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size*2);
226
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size);
229
(void) pthread_mutex_lock(&LOCK_thread_count);
230
if ((error=pthread_create(&signal_thread, &thr_attr, signal_hand, 0)))
232
errmsg_printf(ERRMSG_LVL_ERROR, _("Can't create interrupt-thread (error %d, errno: %d)"),
236
(void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
237
pthread_mutex_unlock(&LOCK_thread_count);
239
(void) pthread_attr_destroy(&thr_attr);
245
This is mainly needed when running with purify, but it's still nice to
246
know that all child threads have died when drizzled exits.
248
static int deinit(drizzled::plugin::Registry&)
252
Wait up to 10 seconds for signal thread to die. We use this mainly to
253
avoid getting warnings that internal::my_thread_end has not been called
255
for (i= 0 ; i < 100 && signal_thread_in_use; i++)
257
if (pthread_kill(signal_thread, SIGTERM) != ESRCH)
259
usleep(100); // Give it time to die
265
static drizzle_sys_var* system_variables[]= {
281
static int init(drizzled::module::Context& context)
283
context.add(new SignalHandler);
289
269
DRIZZLE_DECLARE_PLUGIN
291
271
DRIZZLE_VERSION_ID,