Drizzled Public API Documentation

signal_handler.cc
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <signal.h>
00023 
00024 #include <drizzled/signal_handler.h>
00025 #include <drizzled/drizzled.h>
00026 #include <drizzled/session.h>
00027 #include <drizzled/session/cache.h>
00028 #include <drizzled/internal/my_sys.h>
00029 #include <drizzled/probes.h>
00030 #include <drizzled/plugin.h>
00031 #include <drizzled/plugin/scheduler.h>
00032 #include <drizzled/current_session.h>
00033 #include <drizzled/util/backtrace.h>
00034 #include <drizzled/statistics_variables.h>
00035 #include <drizzled/system_variables.h>
00036 
00037 using namespace drizzled;
00038 
00039 static uint32_t killed_threads;
00040 static bool segfaulted= false;
00041 
00042 /*
00043  * We declare these extern "C" because they are passed to system callback functions
00044  * and Sun Studio does not like it when those don't have C linkage. We prefix them
00045  * because extern "C"-ing something effectively removes the namespace from the
00046  * linker symbols, meaning they would be exporting symbols like "print_signal_warning
00047  */
00048 extern "C"
00049 {
00050 
00051 void drizzled_print_signal_warning(int sig)
00052 {
00053   if (global_system_variables.log_warnings)
00054     errmsg_printf(error::WARN, _("Got signal %d from thread %"PRIu32),
00055                   sig, global_thread_id);
00056 #ifndef HAVE_BSD_SIGNALS
00057   sigset_t set;
00058   sigemptyset(&set);
00059 
00060   struct sigaction sa;
00061   sa.sa_handler= drizzled_print_signal_warning;
00062   sa.sa_mask= set;
00063   sa.sa_flags= 0;
00064   sigaction(sig, &sa, NULL);  /* int. thread system calls */
00065 #endif
00066   if (sig == SIGALRM)
00067     alarm(2);         /* reschedule alarm */
00068 }
00069 
00071 void drizzled_end_thread_signal(int )
00072 {
00073   Session *session= current_session;
00074   if (session)
00075   {
00076     Session::shared_ptr session_ptr(session::Cache::find(session->getSessionId()));
00077     if (not session_ptr) // We need to make we have a lock on session before we do anything with it.
00078       return;
00079 
00080     killed_threads++;
00081 
00082     // We need to get the ID before we kill off the session
00083     session_ptr->scheduler->killSessionNow(session_ptr);
00084     DRIZZLE_CONNECTION_DONE(session_ptr->getSessionId());
00085   }
00086 }
00087 
00088 static void write_core(int sig)
00089 {
00090   signal(sig, SIG_DFL);
00091 #ifdef HAVE_gcov
00092   /*
00093     For GCOV build, crashing will prevent the writing of code coverage
00094     information from this process, causing gcov output to be incomplete.
00095     So we force the writing of coverage information here before terminating.
00096   */
00097   extern void __gcov_flush(void);
00098   __gcov_flush();
00099 #endif
00100   pthread_kill(pthread_self(), sig);
00101 #if defined(P_MYID) && !defined(SCO)
00102   /* On Solaris, the above kill is not enough */
00103   sigsend(P_PID,P_MYID,sig);
00104 #endif
00105 }
00106 
00107 void drizzled_handle_segfault(int sig)
00108 {
00109   time_t curr_time;
00110   struct tm tm;
00111 
00112   /*
00113     Strictly speaking, one needs a mutex here
00114     but since we have got SIGSEGV already, things are a mess
00115     so not having the mutex is not as bad as possibly using a buggy
00116     mutex - so we keep things simple
00117   */
00118   if (segfaulted)
00119   {
00120     fprintf(stderr, _("Fatal signal %d while backtracing\n"), sig);
00121     exit(1);
00122   }
00123 
00124   segfaulted= true;
00125 
00126   curr_time= time(NULL);
00127   if(curr_time == (time_t)-1)
00128   {
00129     fprintf(stderr, _("Fatal: time() call failed\n"));
00130     exit(1);
00131   }
00132 
00133   localtime_r(&curr_time, &tm);
00134   
00135   fprintf(stderr,_("%02d%02d%02d %2d:%02d:%02d - drizzled got signal %d;\n"
00136           "This could be because you hit a bug. It is also possible that "
00137           "this binary\n or one of the libraries it was linked against is "
00138           "corrupt, improperly built,\n or misconfigured. This error can "
00139           "also be caused by malfunctioning hardware.\n"),
00140           tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
00141           tm.tm_hour, tm.tm_min, tm.tm_sec,
00142           sig);
00143   fprintf(stderr, _("We will try our best to scrape up some info that "
00144                     "will hopefully help diagnose\n"
00145                     "the problem, but since we have already crashed, "
00146                     "something is definitely wrong\nand this may fail.\n\n"));
00147   fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
00148   fprintf(stderr, "max_used_connections=%"PRIu64"\n", current_global_counters.max_used_connections);
00149   fprintf(stderr, "connection_count=%u\n", uint32_t(connection_count));
00150   fprintf(stderr, _("It is possible that drizzled could use up to \n"
00151                     "(read_buffer_size + sort_buffer_size)*thread_count\n"
00152                     "bytes of memory\n"
00153                     "Hope that's ok; if not, decrease some variables in the "
00154                     "equation.\n\n"));
00155 
00156   call_backtrace();
00157 
00158   write_core(sig);
00159 
00160   exit(1);
00161 }
00162 
00163 } /* extern "C" */