~drizzle-trunk/drizzle/development

900 by Brian Aker
Creating signal handler plugin.
1
/* Copyright (C) 2006 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
16
#include <drizzled/server_includes.h>
17
#include <drizzled/gettext.h>
18
#include <drizzled/error.h>
1022.2.2 by Monty Taylor
Small cleanup inspired by merge.
19
#include <drizzled/unireg.h>
900 by Brian Aker
Creating signal handler plugin.
20
21
static bool kill_in_progress= false;
22
static bool volatile signal_thread_in_use= false;
23
extern int cleanup_done;
24
25
26
/* Prototypes -> all of these should be factored out into a propper shutdown */
27
void close_connections(void);
1019.1.6 by Brian Aker
A number of random cleanups.
28
bool reload_cache(Session *session, ulong options, TableList *tables);
900 by Brian Aker
Creating signal handler plugin.
29
30
31
/**
32
  Force server down. Kill all connections and threads and exit.
33
34
  @param  sig_ptr       Signal number that caused kill_server to be called.
35
36
  @note
37
    A signal number of 0 mean that the function was not called
38
    from a signal handler and there is thus no signal to block
39
    or stop, we just want to kill the server.
40
*/
41
1022.2.18 by Monty Taylor
Fixed the fix on solaris.
42
static void kill_server(void *sig_ptr)
900 by Brian Aker
Creating signal handler plugin.
43
{
44
  int sig=(int) (long) sig_ptr;			// This is passed a int
45
  // if there is a signal during the kill in progress, ignore the other
46
  if (kill_in_progress)				// Safety
1022.2.18 by Monty Taylor
Fixed the fix on solaris.
47
    return;
900 by Brian Aker
Creating signal handler plugin.
48
  kill_in_progress=true;
49
  abort_loop=1;					// This should be set
50
  if (sig != 0) // 0 is not a valid signal number
51
    my_sigset(sig, SIG_IGN);                    /* purify inspected */
52
  if (sig == SIGTERM || sig == 0)
53
    errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),my_progname);
54
  else
55
    errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),my_progname,sig); /* purecov: inspected */
56
57
  close_connections();
58
  if (sig != SIGTERM && sig != 0)
59
    unireg_abort(1);				/* purecov: inspected */
60
  else
61
    unireg_end();
62
}
63
64
/**
65
  Create file to store pid number.
66
*/
67
static void create_pid_file()
68
{
914.2.1 by Brian Aker
Cleanup pid handler.
69
  int file;
70
  char buff[1024];
71
72
  assert(pidfile_name[0]);
73
  if ((file = open(pidfile_name, O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU|S_IRGRP|S_IROTH)) > 0)
900 by Brian Aker
Creating signal handler plugin.
74
  {
914.2.1 by Brian Aker
Cleanup pid handler.
75
    int length;
76
77
    length= snprintf(buff, 1024, "%ld\n", (long) getpid()); 
78
79
    if ((write(file, buff, length)) == length)
900 by Brian Aker
Creating signal handler plugin.
80
    {
914.2.1 by Brian Aker
Cleanup pid handler.
81
      if (close(file) != -1)
82
        return;
900 by Brian Aker
Creating signal handler plugin.
83
    }
914.2.1 by Brian Aker
Cleanup pid handler.
84
    (void)close(file); /* We can ignore the error, since we are going to error anyway at this point */
900 by Brian Aker
Creating signal handler plugin.
85
  }
914.2.1 by Brian Aker
Cleanup pid handler.
86
  snprintf(buff, 1024, "Can't start server: can't create PID file (%s)", pidfile_name);
87
  sql_perror(buff);
900 by Brian Aker
Creating signal handler plugin.
88
  exit(1);
89
}
90
91
92
/** This threads handles all signals and alarms. */
93
/* ARGSUSED */
907.3.5 by Monty Taylor
Fixed new 64-bit caused solaris warnings.
94
extern "C"
900 by Brian Aker
Creating signal handler plugin.
95
pthread_handler_t signal_hand(void *)
96
{
97
  sigset_t set;
98
  int sig;
99
  my_thread_init();				// Init new thread
100
  signal_thread_in_use= true;
101
102
  if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
103
  {
104
    (void) sigemptyset(&set);			// Setup up SIGINT for debug
105
    (void) sigaddset(&set,SIGINT);		// For debugging
106
    (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
107
  }
108
  (void) sigemptyset(&set);			// Setup up SIGINT for debug
109
#ifndef IGNORE_SIGHUP_SIGQUIT
110
  (void) sigaddset(&set,SIGQUIT);
111
  (void) sigaddset(&set,SIGHUP);
112
#endif
113
  (void) sigaddset(&set,SIGTERM);
114
  (void) sigaddset(&set,SIGTSTP);
115
116
  /* Save pid to this process (or thread on Linux) */
117
  create_pid_file();
118
119
#ifdef HAVE_STACK_TRACE_ON_SEGV
120
  if (opt_do_pstack)
121
  {
122
    sprintf(pstack_file_name,"drizzled-%lu-%%d-%%d.backtrace", (uint32_t)getpid());
123
    pstack_install_segv_action(pstack_file_name);
124
  }
125
#endif /* HAVE_STACK_TRACE_ON_SEGV */
126
127
  /*
905 by Brian Aker
Code cleanup in signal_handler.cc
128
    signal to init that we are ready
129
    This works by waiting for init to free mutex,
900 by Brian Aker
Creating signal handler plugin.
130
    after which we signal it that we are ready.
131
    At this pointer there is no other threads running, so there
132
    should not be any other pthread_cond_signal() calls.
133
134
    We call lock/unlock to out wait any thread/session which is
135
    dieing. Since only comes from this code, this should be safe.
136
    (Asked MontyW over the phone about this.) -Brian
137
138
  */
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);
142
143
  (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
144
  for (;;)
145
  {
146
    int error;					// Used when debugging
147
    if (shutdown_in_progress && !abort_loop)
148
    {
149
      sig= SIGTERM;
150
      error=0;
151
    }
152
    else
153
      while ((error= sigwait(&set,&sig)) == EINTR) ;
154
    if (cleanup_done)
155
    {
156
      my_thread_end();
157
      signal_thread_in_use= false;
158
159
      return NULL;
160
    }
161
    switch (sig) {
162
    case SIGTERM:
163
    case SIGQUIT:
164
    case SIGKILL:
165
      /* switch to the old log message processing */
166
      if (!abort_loop)
167
      {
168
        abort_loop=1;				// mark abort for threads
169
        kill_server((void*) sig);	// MIT THREAD has a alarm thread
170
      }
171
      break;
172
    case SIGHUP:
173
      if (!abort_loop)
1019.1.6 by Brian Aker
A number of random cleanups.
174
        reload_cache(NULL, (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST ), NULL); // Flush logs
900 by Brian Aker
Creating signal handler plugin.
175
      break;
176
    default:
177
      break;					/* purecov: tested */
178
    }
179
  }
180
}
181
182
971.1.52 by Monty Taylor
Did the finalizers. Renamed plugin_registry.
183
static int init(PluginRegistry&)
900 by Brian Aker
Creating signal handler plugin.
184
{
185
  int error;
186
  pthread_attr_t thr_attr;
187
  size_t my_thread_stack_size= 65536;
188
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);
192
  {
193
    struct sched_param tmp_sched_param;
194
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);
198
  }
199
#if defined(__ia64__) || defined(__ia64)
200
  /*
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
203
  */
204
  pthread_attr_setstacksize(&thr_attr, my_thread_stack_size*2);
205
# else
206
  pthread_attr_setstacksize(&thr_attr, my_thread_stack_size);
207
#endif
208
209
  (void) pthread_mutex_lock(&LOCK_thread_count);
210
  if ((error=pthread_create(&signal_thread, &thr_attr, signal_hand, 0)))
211
  {
212
      errmsg_printf(ERRMSG_LVL_ERROR, _("Can't create interrupt-thread (error %d, errno: %d)"),
213
                    error,errno);
214
    exit(1);
215
  }
216
  (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
217
  pthread_mutex_unlock(&LOCK_thread_count);
218
219
  (void) pthread_attr_destroy(&thr_attr);
905 by Brian Aker
Code cleanup in signal_handler.cc
220
900 by Brian Aker
Creating signal handler plugin.
221
  return 0;
222
}
223
224
/**
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.
227
*/
971.1.52 by Monty Taylor
Did the finalizers. Renamed plugin_registry.
228
static int deinit(PluginRegistry&)
900 by Brian Aker
Creating signal handler plugin.
229
{
230
  uint32_t i;
231
  /*
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
234
  */
235
  for (i= 0 ; i < 100 && signal_thread_in_use; i++)
236
  {
237
    if (pthread_kill(signal_thread, SIGTERM) != ESRCH)
238
      break;
239
    usleep(100);				// Give it time to die
240
  }
241
242
  return 0;
243
}
244
245
static struct st_mysql_sys_var* system_variables[]= {
246
  NULL
247
};
248
249
drizzle_declare_plugin(signal_handler)
250
{
251
  "signal_handler",
252
  "0.1",
253
  "Brian Aker",
254
  "Default Signal Handler",
255
  PLUGIN_LICENSE_GPL,
256
  init, /* Plugin Init */
257
  deinit, /* Plugin Deinit */
258
  NULL,   /* status variables */
259
  system_variables,   /* system variables */
260
  NULL    /* config options */
261
}
262
drizzle_declare_plugin_end;