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 
00034 #include <drizzled/util/backtrace.h>
00035 
00036 using namespace drizzled;
00037 
00038 static uint32_t killed_threads;
00039 static bool segfaulted= false;
00040 
00041 /*
00042  * We declare these extern "C" because they are passed to system callback functions
00043  * and Sun Studio does not like it when those don't have C linkage. We prefix them
00044  * because extern "C"-ing something effectively removes the namespace from the
00045  * linker symbols, meaning they would be exporting symbols like "print_signal_warning
00046  */
00047 extern "C"
00048 {
00049 
00050 void drizzled_print_signal_warning(int sig)
00051 {
00052   if (global_system_variables.log_warnings)
00053     errmsg_printf(error::WARN, _("Got signal %d from thread %"PRIu32),
00054                   sig, global_thread_id);
00055 #ifndef HAVE_BSD_SIGNALS
00056   sigset_t set;
00057   sigemptyset(&set);
00058 
00059   struct sigaction sa;
00060   sa.sa_handler= drizzled_print_signal_warning;
00061   sa.sa_mask= set;
00062   sa.sa_flags= 0;
00063   sigaction(sig, &sa, NULL);  /* int. thread system calls */
00064 #endif
00065   if (sig == SIGALRM)
00066     alarm(2);         /* reschedule alarm */
00067 }
00068 
00070 void drizzled_end_thread_signal(int )
00071 {
00072   Session *session= current_session;
00073   if (session)
00074   {
00075     Session::shared_ptr session_ptr(session::Cache::singleton().find(session->getSessionId()));
00076     if (not session_ptr) // We need to make we have a lock on session before we do anything with it.
00077       return;
00078 
00079     killed_threads++;
00080 
00081     // We need to get the ID before we kill off the session
00082     session_ptr->scheduler->killSessionNow(session_ptr);
00083     DRIZZLE_CONNECTION_DONE(session_ptr->getSessionId());
00084   }
00085 }
00086 
00087 static void write_core(int sig)
00088 {
00089   signal(sig, SIG_DFL);
00090 #ifdef HAVE_gcov
00091   /*
00092     For GCOV build, crashing will prevent the writing of code coverage
00093     information from this process, causing gcov output to be incomplete.
00094     So we force the writing of coverage information here before terminating.
00095   */
00096   extern void __gcov_flush(void);
00097   __gcov_flush();
00098 #endif
00099   pthread_kill(pthread_self(), sig);
00100 #if defined(P_MYID) && !defined(SCO)
00101   /* On Solaris, the above kill is not enough */
00102   sigsend(P_PID,P_MYID,sig);
00103 #endif
00104 }
00105 
00106 void drizzled_handle_segfault(int sig)
00107 {
00108   time_t curr_time;
00109   struct tm tm;
00110 
00111   /*
00112     Strictly speaking, one needs a mutex here
00113     but since we have got SIGSEGV already, things are a mess
00114     so not having the mutex is not as bad as possibly using a buggy
00115     mutex - so we keep things simple
00116   */
00117   if (segfaulted)
00118   {
00119     fprintf(stderr, _("Fatal signal %d while backtracing\n"), sig);
00120     exit(1);
00121   }
00122 
00123   segfaulted= true;
00124 
00125   curr_time= time(NULL);
00126   if(curr_time == (time_t)-1)
00127   {
00128     fprintf(stderr, _("Fatal: time() call failed\n"));
00129     exit(1);
00130   }
00131 
00132   localtime_r(&curr_time, &tm);
00133   
00134   fprintf(stderr,_("%02d%02d%02d %2d:%02d:%02d - drizzled got signal %d;\n"
00135           "This could be because you hit a bug. It is also possible that "
00136           "this binary\n or one of the libraries it was linked against is "
00137           "corrupt, improperly built,\n or misconfigured. This error can "
00138           "also be caused by malfunctioning hardware.\n"),
00139           tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
00140           tm.tm_hour, tm.tm_min, tm.tm_sec,
00141           sig);
00142   fprintf(stderr, _("We will try our best to scrape up some info that "
00143                     "will hopefully help diagnose\n"
00144                     "the problem, but since we have already crashed, "
00145                     "something is definitely wrong\nand this may fail.\n\n"));
00146   fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
00147   fprintf(stderr, "max_used_connections=%"PRIu64"\n", current_global_counters.max_used_connections);
00148   fprintf(stderr, "connection_count=%u\n", uint32_t(connection_count));
00149   fprintf(stderr, _("It is possible that drizzled could use up to \n"
00150                     "(read_buffer_size + sort_buffer_size)*thread_count\n"
00151                     "bytes of memory\n"
00152                     "Hope that's ok; if not, decrease some variables in the "
00153                     "equation.\n\n"));
00154 
00155   drizzled::util::custom_backtrace();
00156 
00157   write_core(sig);
00158 
00159   exit(1);
00160 }
00161 
00162 } /* extern "C" */