~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/signal_handler/signal_handler.cc

move POW() and POWER() function into math_functions plugin

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
   Copyright (C) 2011 Brian Aker
3
 
   Copyright (C) 2006 MySQL AB
 
1
/* Copyright (C) 2006 MySQL AB
4
2
 
5
3
   This program is free software; you can redistribute it and/or modify
6
4
   it under the terms of the GNU General Public License as published by
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 */
17
15
 
18
 
#include <config.h>
19
 
 
 
16
#include "config.h"
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>
29
 
 
30
 
#include <drizzled/session.h>
31
 
#include <drizzled/session/cache.h>
32
 
 
33
 
#include <drizzled/debug.h>
34
 
 
35
 
#include <drizzled/drizzled.h>
36
 
 
37
 
#include <drizzled/refresh_version.h>
38
 
 
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"
 
25
#include "drizzled/plugin/daemon.h"
 
26
#include "drizzled/signal_handler.h"
 
27
 
 
28
#include "drizzled/drizzled.h"
41
29
 
42
30
#include <sys/stat.h>
43
31
#include <fcntl.h>
44
32
 
45
33
 
46
34
static bool kill_in_progress= false;
47
 
void signal_hand(void);
 
35
extern "C" pthread_handler_t signal_hand(void *);
48
36
 
49
37
namespace drizzled
50
38
{
51
39
extern int cleanup_done;
52
40
extern bool volatile abort_loop;
53
41
extern bool volatile shutdown_in_progress;
54
 
extern boost::filesystem::path pid_file;
 
42
extern char pidfile_name[FN_REFLEN];
55
43
/* Prototypes -> all of these should be factored out into a propper shutdown */
56
44
extern void close_connections(void);
 
45
extern std::bitset<12> test_flags;
57
46
}
58
47
 
59
48
using namespace drizzled;
60
49
 
61
50
 
62
51
 
63
 
 
64
52
/**
65
53
  Force server down. Kill all connections and threads and exit.
66
54
 
72
60
    or stop, we just want to kill the server.
73
61
*/
74
62
 
75
 
static void kill_server(int sig)
 
63
static void kill_server(void *sig_ptr)
76
64
{
 
65
  int sig=(int) (long) sig_ptr;                 // This is passed a int
77
66
  // if there is a signal during the kill in progress, ignore the other
78
67
  if (kill_in_progress)                         // Safety
79
68
    return;
82
71
  if (sig != 0) // 0 is not a valid signal number
83
72
    ignore_signal(sig);                    /* purify inspected */
84
73
  if (sig == SIGTERM || sig == 0)
85
 
    errmsg_printf(error::INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
 
74
    errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
86
75
  else
87
 
    errmsg_printf(error::ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
88
 
 
 
76
    errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
89
77
  close_connections();
90
78
  clean_up(1);
91
79
}
98
86
  int file;
99
87
  char buff[1024];
100
88
 
101
 
  if ((file = open(pid_file.file_string().c_str(), O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU|S_IRGRP|S_IROTH)) > 0)
 
89
  assert(pidfile_name[0]);
 
90
  if ((file = open(pidfile_name, O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU|S_IRGRP|S_IROTH)) > 0)
102
91
  {
103
92
    int length;
104
93
 
111
100
    }
112
101
    (void)close(file); /* We can ignore the error, since we are going to error anyway at this point */
113
102
  }
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());
 
103
  snprintf(buff, 1024, "Can't start server: can't create PID file (%s)", pidfile_name);
116
104
  sql_perror(buff);
117
105
  exit(1);
118
106
}
119
107
 
120
108
 
121
109
/** This threads handles all signals and alarms. */
122
 
void signal_hand()
 
110
pthread_handler_t signal_hand(void *)
123
111
{
124
112
  sigset_t set;
125
113
  int sig;
126
114
  internal::my_thread_init();                           // Init new thread
127
 
  boost::this_thread::at_thread_exit(&internal::my_thread_end);
128
115
  signal_thread_in_use= true;
129
116
 
130
 
  if ((drizzled::getDebug().test(drizzled::debug::ALLOW_SIGINT)))
 
117
  if ((test_flags.test(TEST_SIGINT)))
131
118
  {
132
119
    (void) sigemptyset(&set);                   // Setup up SIGINT for debug
133
120
    (void) sigaddset(&set,SIGINT);              // For debugging
134
 
    (void) pthread_sigmask(SIG_UNBLOCK, &set, NULL);
 
121
    (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
135
122
  }
136
123
  (void) sigemptyset(&set);                     // Setup up SIGINT for debug
137
124
#ifndef IGNORE_SIGHUP_SIGQUIT
138
 
  if (sigaddset(&set,SIGQUIT))
139
 
  {
140
 
    std::cerr << "failed setting sigaddset() with SIGQUIT\n";
141
 
  }
142
 
  if (sigaddset(&set,SIGHUP))
143
 
  {
144
 
    std::cerr << "failed setting sigaddset() with SIGHUP\n";
145
 
  }
 
125
  (void) sigaddset(&set,SIGQUIT);
 
126
  (void) sigaddset(&set,SIGHUP);
146
127
#endif
147
 
  if (sigaddset(&set,SIGTERM))
148
 
  {
149
 
    std::cerr << "failed setting sigaddset() with SIGTERM\n";
150
 
  }
151
 
  if (sigaddset(&set,SIGTSTP))
152
 
  {
153
 
    std::cerr << "failed setting sigaddset() with SIGTSTP\n";
154
 
  }
 
128
  (void) sigaddset(&set,SIGTERM);
 
129
  (void) sigaddset(&set,SIGTSTP);
155
130
 
156
131
  /* Save pid to this process (or thread on Linux) */
157
132
  create_pid_file();
168
143
    (Asked MontyW over the phone about this.) -Brian
169
144
 
170
145
  */
171
 
  session::Cache::singleton().mutex().lock();
172
 
  session::Cache::singleton().mutex().unlock();
 
146
  LOCK_thread_count.lock();
 
147
  LOCK_thread_count.unlock();
173
148
  COND_thread_count.notify_all();
174
149
 
175
 
  if (pthread_sigmask(SIG_BLOCK, &set, NULL))
176
 
  {
177
 
    std::cerr << "Failed to set pthread_sigmask() in signal handler\n";
178
 
  }
179
 
 
 
150
  (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
180
151
  for (;;)
181
152
  {
182
153
    int error;                                  // Used when debugging
183
 
 
184
154
    if (shutdown_in_progress && !abort_loop)
185
155
    {
186
156
      sig= SIGTERM;
187
157
      error=0;
188
158
    }
189
159
    else
190
 
    {
191
 
      while ((error= sigwait(&set, &sig)) == EINTR) ;
192
 
    }
193
 
 
 
160
      while ((error= sigwait(&set,&sig)) == EINTR) ;
194
161
    if (cleanup_done)
195
162
    {
 
163
      internal::my_thread_end();
196
164
      signal_thread_in_use= false;
197
165
 
198
 
      return;
 
166
      return NULL;
199
167
    }
200
168
    switch (sig) {
201
169
    case SIGTERM:
202
170
    case SIGQUIT:
203
171
    case SIGKILL:
204
 
    case SIGTSTP:
205
172
      /* switch to the old log message processing */
206
173
      if (!abort_loop)
207
174
      {
208
175
        abort_loop=1;                           // mark abort for threads
209
 
        kill_server(sig);               // MIT THREAD has a alarm thread
 
176
        kill_server((void*) sig);       // MIT THREAD has a alarm thread
210
177
      }
211
178
      break;
212
179
    case SIGHUP:
227
194
{
228
195
  SignalHandler(const SignalHandler &);
229
196
  SignalHandler& operator=(const SignalHandler &);
230
 
  boost::thread thread;
231
 
 
232
197
public:
233
 
  SignalHandler() :
234
 
    drizzled::plugin::Daemon("Signal Handler")
 
198
  SignalHandler()
 
199
    : drizzled::plugin::Daemon("Signal Handler")
235
200
  {
 
201
    int error;
 
202
    pthread_attr_t thr_attr;
 
203
    size_t my_thread_stack_size= 65536;
 
204
 
 
205
    (void) pthread_attr_init(&thr_attr);
 
206
    pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
 
207
    (void) pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED);
 
208
    {
 
209
      struct sched_param tmp_sched_param;
 
210
 
 
211
      memset(&tmp_sched_param, 0, sizeof(tmp_sched_param));
 
212
      tmp_sched_param.sched_priority= INTERRUPT_PRIOR;
 
213
      (void)pthread_attr_setschedparam(&thr_attr, &tmp_sched_param);
 
214
    }
 
215
#if defined(__ia64__) || defined(__ia64)
 
216
    /*
 
217
      Peculiar things with ia64 platforms - it seems we only have half the
 
218
      stack size in reality, so we have to double it here
 
219
    */
 
220
    pthread_attr_setstacksize(&thr_attr, my_thread_stack_size*2);
 
221
# else
 
222
    pthread_attr_setstacksize(&thr_attr, my_thread_stack_size);
 
223
#endif
 
224
 
236
225
    // @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);
 
226
    (void) LOCK_thread_count.lock();
 
227
    if ((error= pthread_create(&signal_thread, &thr_attr, signal_hand, 0)))
 
228
    {
 
229
      errmsg_printf(ERRMSG_LVL_ERROR,
 
230
                    _("Can't create interrupt-thread (error %d, errno: %d)"),
 
231
                    error,errno);
 
232
      exit(1);
 
233
    }
 
234
    pthread_cond_wait(COND_thread_count.native_handle(), LOCK_thread_count.native_handle());
 
235
    LOCK_thread_count.unlock();
 
236
 
 
237
    (void) pthread_attr_destroy(&thr_attr);
241
238
  }
242
239
 
243
240
  /**
250
247
      Wait up to 100000 micro-seconds for signal thread to die. We use this mainly to
251
248
      avoid getting warnings that internal::my_thread_end has not been called
252
249
    */
253
 
    bool completed= false;
254
 
    /*
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
258
 
   */
259
 
    uint32_t count= 2; // How many times to try join and see if the caller died.
260
 
    while (not completed and count--)
 
250
    for (uint32_t i= 0 ; i < 100 && signal_thread_in_use; i++)
261
251
    {
262
 
      int error;
263
 
      int signal= count == 1 ? SIGTSTP : SIGTERM;
264
 
      
265
 
      if ((error= pthread_kill(thread.native_handle(), signal)))
266
 
      {
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";
 
252
      if (pthread_kill(signal_thread, SIGTERM) != ESRCH)
270
253
        break;
271
 
      }
272
 
      else
273
 
      {
274
 
        boost::posix_time::milliseconds duration(100);
275
 
        completed= thread.timed_join(duration);
276
 
      }
 
254
 
 
255
      struct timespec tm;
 
256
      tm.tv_sec= 0;
 
257
      tm.tv_nsec= 100000;
 
258
 
 
259
      nanosleep(&tm, NULL);                             // Give it time to die
277
260
    }
 
261
 
278
262
  }
279
263
};
280
264
 
281
265
static int init(drizzled::module::Context& context)
282
266
{
283
 
  context.add(new SignalHandler);
284
 
 
 
267
  SignalHandler *handler= new SignalHandler;
 
268
  context.add(handler);
285
269
  return 0;
286
270
}
287
271
 
288
272
 
 
273
static drizzle_sys_var* system_variables[]= {
 
274
  NULL
 
275
};
 
276
 
289
277
DRIZZLE_DECLARE_PLUGIN
290
278
{
291
279
  DRIZZLE_VERSION_ID,
295
283
  "Default Signal Handler",
296
284
  PLUGIN_LICENSE_GPL,
297
285
  init, /* Plugin Init */
298
 
  NULL,   /* depends */
 
286
  system_variables,   /* system variables */
299
287
  NULL    /* config options */
300
288
}
301
289
DRIZZLE_DECLARE_PLUGIN_END;