~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/drizzled.cc

  • Committer: Brian Aker
  • Date: 2009-02-26 19:51:30 UTC
  • Revision ID: brian@tangent.org-20090226195130-tp0vdn5mqulw99f9
Creating signal handler plugin.

Show diffs side-by-side

added added

removed removed

Lines of Context:
168
168
 
169
169
} /* cplusplus */
170
170
 
171
 
#define DRIZZLE_KILL_SIGNAL SIGTERM
172
 
 
173
171
#include <mysys/my_pthread.h>                   // For thr_setconcurency()
174
172
 
175
173
#include <drizzled/gettext.h>
237
235
/* static variables */
238
236
 
239
237
/* the default log output is log tables */
240
 
static bool volatile select_thread_in_use, signal_thread_in_use;
 
238
static bool volatile select_thread_in_use;
241
239
static bool volatile ready_to_exit;
242
240
static bool opt_debugging= 0;
243
241
static uint32_t wake_thread;
434
432
 
435
433
/* Static variables */
436
434
 
437
 
static bool kill_in_progress, segfaulted;
 
435
static bool segfaulted;
438
436
#ifdef HAVE_STACK_TRACE_ON_SEGV
439
437
static bool opt_do_pstack;
440
438
#endif /* HAVE_STACK_TRACE_ON_SEGV */
441
 
static int cleanup_done;
 
439
int cleanup_done;
442
440
static char *drizzle_home_ptr, *pidfile_name_ptr;
443
441
static int defaults_argc;
444
442
static char **defaults_argv;
476
474
static void clean_up(bool print_message);
477
475
 
478
476
static void usage(void);
479
 
static void start_signal_handler(void);
480
477
static void close_server_sock();
481
478
static void clean_up_mutexes(void);
482
 
static void wait_for_signal_thread_to_end(void);
483
 
static void create_pid_file();
484
479
static void drizzled_exit(int exit_code) __attribute__((noreturn));
485
480
extern "C" bool safe_read_error_impl(NET *net);
486
481
 
488
483
** Code to end drizzled
489
484
****************************************************************************/
490
485
 
491
 
static void close_connections(void)
 
486
void close_connections(void)
492
487
{
493
488
 
494
489
  /* kill connection thread */
615
610
}
616
611
 
617
612
 
618
 
 
619
 
/**
620
 
  Force server down. Kill all connections and threads and exit.
621
 
 
622
 
  @param  sig_ptr       Signal number that caused kill_server to be called.
623
 
 
624
 
  @note
625
 
    A signal number of 0 mean that the function was not called
626
 
    from a signal handler and there is thus no signal to block
627
 
    or stop, we just want to kill the server.
628
 
*/
629
 
 
630
 
static void *kill_server(void *sig_ptr)
631
 
#define RETURN_FROM_KILL_SERVER return(0)
632
 
{
633
 
  int sig=(int) (long) sig_ptr;                 // This is passed a int
634
 
  // if there is a signal during the kill in progress, ignore the other
635
 
  if (kill_in_progress)                         // Safety
636
 
    RETURN_FROM_KILL_SERVER;
637
 
  kill_in_progress=true;
638
 
  abort_loop=1;                                 // This should be set
639
 
  if (sig != 0) // 0 is not a valid signal number
640
 
    my_sigset(sig, SIG_IGN);                    /* purify inspected */
641
 
  if (sig == DRIZZLE_KILL_SIGNAL || sig == 0)
642
 
    errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),my_progname);
643
 
  else
644
 
    errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),my_progname,sig); /* purecov: inspected */
645
 
 
646
 
  close_connections();
647
 
  if (sig != DRIZZLE_KILL_SIGNAL &&
648
 
      sig != 0)
649
 
    unireg_abort(1);                            /* purecov: inspected */
650
 
  else
651
 
    unireg_end();
652
 
 
653
 
  /* purecov: begin deadcode */
654
 
 
655
 
  my_thread_end();
656
 
  pthread_exit(0);
657
 
  /* purecov: end */
658
 
 
659
 
  RETURN_FROM_KILL_SERVER;
660
 
}
661
 
 
662
 
 
663
613
extern "C" void print_signal_warning(int sig)
664
614
{
665
615
  if (global_system_variables.log_warnings)
700
650
  @note
701
651
    This function never returns.
702
652
*/
703
 
void unireg_end(void)
 
653
extern "C" void unireg_end(void)
704
654
{
705
655
  clean_up(1);
706
656
  my_thread_end();
726
676
 
727
677
static void drizzled_exit(int exit_code)
728
678
{
729
 
  wait_for_signal_thread_to_end();
730
679
  clean_up_mutexes();
731
680
  my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
732
681
  exit(exit_code); /* purecov: inspected */
786
735
} /* clean_up */
787
736
 
788
737
 
789
 
/**
790
 
  This is mainly needed when running with purify, but it's still nice to
791
 
  know that all child threads have died when drizzled exits.
792
 
*/
793
 
static void wait_for_signal_thread_to_end()
794
 
{
795
 
  uint32_t i;
796
 
  /*
797
 
    Wait up to 10 seconds for signal thread to die. We use this mainly to
798
 
    avoid getting warnings that my_thread_end has not been called
799
 
  */
800
 
  for (i= 0 ; i < 100 && signal_thread_in_use; i++)
801
 
  {
802
 
    if (pthread_kill(signal_thread, DRIZZLE_KILL_SIGNAL) != ESRCH)
803
 
      break;
804
 
    usleep(100);                                // Give it time to die
805
 
  }
806
 
}
807
 
 
808
 
 
809
738
static void clean_up_mutexes()
810
739
{
811
740
  (void) pthread_mutex_destroy(&LOCK_drizzleclient_create_db);
1394
1323
  return;;
1395
1324
}
1396
1325
 
1397
 
 
1398
 
static void start_signal_handler(void)
1399
 
{
1400
 
  int error;
1401
 
  pthread_attr_t thr_attr;
1402
 
 
1403
 
  (void) pthread_attr_init(&thr_attr);
1404
 
  pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
1405
 
  (void) pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED);
1406
 
  {
1407
 
    struct sched_param tmp_sched_param;
1408
 
 
1409
 
    memset(&tmp_sched_param, 0, sizeof(tmp_sched_param));
1410
 
    tmp_sched_param.sched_priority= INTERRUPT_PRIOR;
1411
 
    (void)pthread_attr_setschedparam(&thr_attr, &tmp_sched_param);
1412
 
  }
1413
 
#if defined(__ia64__) || defined(__ia64)
1414
 
  /*
1415
 
    Peculiar things with ia64 platforms - it seems we only have half the
1416
 
    stack size in reality, so we have to double it here
1417
 
  */
1418
 
  pthread_attr_setstacksize(&thr_attr,my_thread_stack_size*2);
1419
 
# else
1420
 
  pthread_attr_setstacksize(&thr_attr,my_thread_stack_size);
1421
 
#endif
1422
 
 
1423
 
  (void) pthread_mutex_lock(&LOCK_thread_count);
1424
 
  if ((error=pthread_create(&signal_thread,&thr_attr,signal_hand,0)))
1425
 
  {
1426
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Can't create interrupt-thread (error %d, errno: %d)"),
1427
 
                    error,errno);
1428
 
    exit(1);
1429
 
  }
1430
 
  (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
1431
 
  pthread_mutex_unlock(&LOCK_thread_count);
1432
 
 
1433
 
  (void) pthread_attr_destroy(&thr_attr);
1434
 
  return;;
1435
 
}
1436
 
 
1437
 
 
1438
 
/** This threads handles all signals and alarms. */
1439
 
/* ARGSUSED */
1440
 
pthread_handler_t signal_hand(void *)
1441
 
{
1442
 
  sigset_t set;
1443
 
  int sig;
1444
 
  my_thread_init();                             // Init new thread
1445
 
  signal_thread_in_use= 1;
1446
 
 
1447
 
  if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
1448
 
  {
1449
 
    (void) sigemptyset(&set);                   // Setup up SIGINT for debug
1450
 
    (void) sigaddset(&set,SIGINT);              // For debugging
1451
 
    (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
1452
 
  }
1453
 
  (void) sigemptyset(&set);                     // Setup up SIGINT for debug
1454
 
#ifndef IGNORE_SIGHUP_SIGQUIT
1455
 
  (void) sigaddset(&set,SIGQUIT);
1456
 
  (void) sigaddset(&set,SIGHUP);
1457
 
#endif
1458
 
  (void) sigaddset(&set,SIGTERM);
1459
 
  (void) sigaddset(&set,SIGTSTP);
1460
 
 
1461
 
  /* Save pid to this process (or thread on Linux) */
1462
 
  create_pid_file();
1463
 
 
1464
 
#ifdef HAVE_STACK_TRACE_ON_SEGV
1465
 
  if (opt_do_pstack)
1466
 
  {
1467
 
    sprintf(pstack_file_name,"drizzled-%lu-%%d-%%d.backtrace", (uint32_t)getpid());
1468
 
    pstack_install_segv_action(pstack_file_name);
1469
 
  }
1470
 
#endif /* HAVE_STACK_TRACE_ON_SEGV */
1471
 
 
1472
 
  /*
1473
 
    signal to start_signal_handler that we are ready
1474
 
    This works by waiting for start_signal_handler to free mutex,
1475
 
    after which we signal it that we are ready.
1476
 
    At this pointer there is no other threads running, so there
1477
 
    should not be any other pthread_cond_signal() calls.
1478
 
 
1479
 
    We call lock/unlock to out wait any thread/session which is
1480
 
    dieing. Since only comes from this code, this should be safe.
1481
 
    (Asked MontyW over the phone about this.) -Brian
1482
 
 
1483
 
  */
1484
 
  if (pthread_mutex_lock(&LOCK_thread_count) == 0)
1485
 
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1486
 
  (void) pthread_cond_broadcast(&COND_thread_count);
1487
 
 
1488
 
  (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
1489
 
  for (;;)
1490
 
  {
1491
 
    int error;                                  // Used when debugging
1492
 
    if (shutdown_in_progress && !abort_loop)
1493
 
    {
1494
 
      sig= SIGTERM;
1495
 
      error=0;
1496
 
    }
1497
 
    else
1498
 
      while ((error= sigwait(&set,&sig)) == EINTR) ;
1499
 
    if (cleanup_done)
1500
 
    {
1501
 
      my_thread_end();
1502
 
      signal_thread_in_use= 0;
1503
 
      return NULL;
1504
 
    }
1505
 
    switch (sig) {
1506
 
    case SIGTERM:
1507
 
    case SIGQUIT:
1508
 
    case SIGKILL:
1509
 
      /* switch to the old log message processing */
1510
 
      if (!abort_loop)
1511
 
      {
1512
 
        abort_loop=1;                           // mark abort for threads
1513
 
        kill_server((void*) sig);       // MIT THREAD has a alarm thread
1514
 
      }
1515
 
      break;
1516
 
    case SIGHUP:
1517
 
      if (!abort_loop)
1518
 
      {
1519
 
        bool not_used;
1520
 
        reload_cache((Session*) 0,
1521
 
                     (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
1522
 
                      REFRESH_HOSTS),
1523
 
                     (TableList*) 0, &not_used); // Flush logs
1524
 
      }
1525
 
      break;
1526
 
    default:
1527
 
      break;                                    /* purecov: tested */
1528
 
    }
1529
 
  }
1530
 
}
1531
 
 
1532
1326
static void check_data_home(const char *)
1533
1327
{}
1534
1328
 
2075
1869
 
2076
1870
  init_signals();
2077
1871
 
2078
 
  pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size);
 
1872
  pthread_attr_setstacksize(&connection_attrib, my_thread_stack_size);
2079
1873
 
2080
1874
#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
2081
1875
  {
2138
1932
    After this we can't quit by a simple unireg_abort
2139
1933
  */
2140
1934
  error_handler_hook= my_message_sql;
2141
 
  start_signal_handler();                               // Creates pidfile
2142
1935
 
2143
1936
  if (drizzle_rm_tmp_tables() || my_tz_init((Session *)0, default_tz_name))
2144
1937
  {
2145
1938
    abort_loop=1;
2146
1939
    select_thread_in_use=0;
2147
 
    (void) pthread_kill(signal_thread, DRIZZLE_KILL_SIGNAL);
 
1940
    (void) pthread_kill(signal_thread, SIGTERM);
2148
1941
 
2149
1942
    (void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore
2150
1943
 
2237
2030
}
2238
2031
 
2239
2032
 
2240
 
#ifdef SIGNALS_DONT_BREAK_READ
2241
 
inline void kill_broken_server()
2242
 
{
2243
 
  /* hack to get around signals ignored in syscalls for problem OS's */
2244
 
  if ((ip_sock == -1))
2245
 
  {
2246
 
    select_thread_in_use = 0;
2247
 
    /* The following call will never return */
2248
 
    kill_server((void*) DRIZZLE_KILL_SIGNAL);
2249
 
  }
2250
 
}
2251
 
#define MAYBE_BROKEN_SYSCALL kill_broken_server();
2252
 
#else
2253
 
#define MAYBE_BROKEN_SYSCALL
2254
 
#endif
2255
 
 
2256
2033
        /* Handle new connections and spawn new process to handle them */
2257
2034
 
2258
2035
void handle_connections_sockets()
2263
2040
  Session *session;
2264
2041
  struct sockaddr_storage cAddr;
2265
2042
 
2266
 
  MAYBE_BROKEN_SYSCALL;
2267
2043
  while (!abort_loop)
2268
2044
  {
2269
2045
    int number_of;
2276
2052
                errmsg_printf(ERRMSG_LVL_ERROR, _("drizzled: Got error %d from select"),
2277
2053
                          errno); /* purecov: inspected */
2278
2054
      }
2279
 
      MAYBE_BROKEN_SYSCALL
2280
2055
      continue;
2281
2056
    }
2282
2057
    if (number_of == 0)
2288
2063
 
2289
2064
    if (abort_loop)
2290
2065
    {
2291
 
      MAYBE_BROKEN_SYSCALL;
2292
2066
      break;
2293
2067
    }
2294
2068
 
2316
2090
    {
2317
2091
      if ((error_count++ & 255) == 0)           // This can happen often
2318
2092
        sql_perror("Error in accept");
2319
 
      MAYBE_BROKEN_SYSCALL;
2320
2093
      if (errno == ENFILE || errno == EMFILE)
2321
2094
        sleep(1);                               // Give other threads some time
2322
2095
      continue;
3179
2952
  opt_logname= 0;
3180
2953
  opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
3181
2954
  opt_secure_file_priv= 0;
3182
 
  segfaulted= kill_in_progress= 0;
 
2955
  segfaulted= 0;
3183
2956
  cleanup_done= 0;
3184
2957
  defaults_argc= 0;
3185
2958
  defaults_argv= 0;
3189
2962
  slave_open_temp_tables= 0;
3190
2963
  opt_endinfo= using_udf_functions= 0;
3191
2964
  opt_using_transactions= false;
3192
 
  abort_loop= select_thread_in_use= signal_thread_in_use= 0;
 
2965
  abort_loop= select_thread_in_use= 0;
3193
2966
  ready_to_exit= shutdown_in_progress= 0;
3194
2967
  aborted_threads= aborted_connects= 0;
3195
2968
  max_used_connections= 0;
3751
3524
} /* find_bit_type */
3752
3525
 
3753
3526
 
3754
 
/**
3755
 
  Create file to store pid number.
3756
 
*/
3757
 
static void create_pid_file()
3758
 
{
3759
 
  File file;
3760
 
  if ((file = my_create(pidfile_name,0664,
3761
 
                        O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
3762
 
  {
3763
 
    char buff[21], *end;
3764
 
    end= int10_to_str((long) getpid(), buff, 10);
3765
 
    *end++= '\n';
3766
 
    if (!my_write(file, (unsigned char*) buff, (uint32_t) (end-buff), MYF(MY_WME | MY_NABP)))
3767
 
    {
3768
 
      (void) my_close(file, MYF(0));
3769
 
      return;
3770
 
    }
3771
 
    (void) my_close(file, MYF(0));
3772
 
  }
3773
 
  sql_perror("Can't start server: can't create PID file");
3774
 
  exit(1);
3775
 
}
3776
 
 
3777
3527
bool safe_read_error_impl(NET *net)
3778
3528
{
3779
3529
  if (net->vio)