~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/signal_handler/signal_handler.cc

  • Committer: Brian Aker
  • Date: 2010-08-03 20:57:39 UTC
  • mfrom: (1680.6.4 rollup)
  • Revision ID: brian@gaz-20100803205739-7betgobkod41363k
Removes LOCK_system_variables_hash, one goto, drops internall new for std
new (so possible performance regression), fixes bug where Session was not
unlocked correctly.

Show diffs side-by-side

added added

removed removed

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