00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <config.h>
00019
00020 #include <drizzled/gettext.h>
00021 #include <drizzled/error.h>
00022 #include <drizzled/unireg.h>
00023 #include <drizzled/plugin/storage_engine.h>
00024 #include <drizzled/pthread_globals.h>
00025 #include <drizzled/internal/my_pthread.h>
00026 #include <drizzled/internal/my_sys.h>
00027 #include <drizzled/plugin/daemon.h>
00028 #include <drizzled/signal_handler.h>
00029
00030 #include <drizzled/session.h>
00031 #include <drizzled/session/cache.h>
00032
00033 #include <drizzled/debug.h>
00034
00035 #include <drizzled/drizzled.h>
00036
00037 #include <drizzled/refresh_version.h>
00038
00039 #include <boost/thread/thread.hpp>
00040 #include <boost/filesystem.hpp>
00041
00042 #include <sys/stat.h>
00043 #include <fcntl.h>
00044
00045
00046 static bool kill_in_progress= false;
00047 void signal_hand(void);
00048
00049 namespace drizzled
00050 {
00051 extern int cleanup_done;
00052 extern bool volatile abort_loop;
00053 extern bool volatile shutdown_in_progress;
00054 extern boost::filesystem::path pid_file;
00055
00056 extern void close_connections(void);
00057 }
00058
00059 using namespace drizzled;
00060
00061
00062
00063
00075 static void kill_server(int sig)
00076 {
00077
00078 if (kill_in_progress)
00079 return;
00080 kill_in_progress=true;
00081 abort_loop=1;
00082 if (sig != 0)
00083 ignore_signal(sig);
00084 if (sig == SIGTERM || sig == 0)
00085 errmsg_printf(error::INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
00086 else
00087 errmsg_printf(error::ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
00088
00089 close_connections();
00090 clean_up(1);
00091 }
00092
00096 static void create_pid_file()
00097 {
00098 int file;
00099 char buff[1024];
00100
00101 if ((file = open(pid_file.file_string().c_str(), O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU|S_IRGRP|S_IROTH)) > 0)
00102 {
00103 int length;
00104
00105 length= snprintf(buff, 1024, "%ld\n", (long) getpid());
00106
00107 if ((write(file, buff, length)) == length)
00108 {
00109 if (close(file) != -1)
00110 return;
00111 }
00112 (void)close(file);
00113 }
00114 memset(buff, 0, sizeof(buff));
00115 snprintf(buff, sizeof(buff)-1, "Can't start server: can't create PID file (%s)", pid_file.file_string().c_str());
00116 sql_perror(buff);
00117 exit(1);
00118 }
00119
00120
00122 void signal_hand()
00123 {
00124 sigset_t set;
00125 int sig;
00126 internal::my_thread_init();
00127 boost::this_thread::at_thread_exit(&internal::my_thread_end);
00128 signal_thread_in_use= true;
00129
00130 if ((drizzled::getDebug().test(drizzled::debug::ALLOW_SIGINT)))
00131 {
00132 (void) sigemptyset(&set);
00133 (void) sigaddset(&set,SIGINT);
00134 (void) pthread_sigmask(SIG_UNBLOCK, &set, NULL);
00135 }
00136 (void) sigemptyset(&set);
00137 #ifndef IGNORE_SIGHUP_SIGQUIT
00138 if (sigaddset(&set,SIGQUIT))
00139 {
00140 std::cerr << "failed setting sigaddset() with SIGQUIT\n";
00141 }
00142 if (sigaddset(&set,SIGHUP))
00143 {
00144 std::cerr << "failed setting sigaddset() with SIGHUP\n";
00145 }
00146 #endif
00147 if (sigaddset(&set,SIGTERM))
00148 {
00149 std::cerr << "failed setting sigaddset() with SIGTERM\n";
00150 }
00151 if (sigaddset(&set,SIGTSTP))
00152 {
00153 std::cerr << "failed setting sigaddset() with SIGTSTP\n";
00154 }
00155
00156
00157 create_pid_file();
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 session::Cache::singleton().mutex().lock();
00172 session::Cache::singleton().mutex().unlock();
00173 COND_thread_count.notify_all();
00174
00175 if (pthread_sigmask(SIG_BLOCK, &set, NULL))
00176 {
00177 std::cerr << "Failed to set pthread_sigmask() in signal handler\n";
00178 }
00179
00180 for (;;)
00181 {
00182 int error;
00183
00184 if (shutdown_in_progress && !abort_loop)
00185 {
00186 sig= SIGTERM;
00187 error=0;
00188 }
00189 else
00190 {
00191 while ((error= sigwait(&set, &sig)) == EINTR) ;
00192 }
00193
00194 if (cleanup_done)
00195 {
00196 signal_thread_in_use= false;
00197
00198 return;
00199 }
00200 switch (sig) {
00201 case SIGTERM:
00202 case SIGQUIT:
00203 case SIGKILL:
00204 case SIGTSTP:
00205
00206 if (!abort_loop)
00207 {
00208 abort_loop=1;
00209 kill_server(sig);
00210 }
00211 break;
00212 case SIGHUP:
00213 if (!abort_loop)
00214 {
00215 refresh_version++;
00216 drizzled::plugin::StorageEngine::flushLogs(NULL);
00217 }
00218 break;
00219 default:
00220 break;
00221 }
00222 }
00223 }
00224
00225 class SignalHandler :
00226 public drizzled::plugin::Daemon
00227 {
00228 SignalHandler(const SignalHandler &);
00229 SignalHandler& operator=(const SignalHandler &);
00230 boost::thread thread;
00231
00232 public:
00233 SignalHandler() :
00234 drizzled::plugin::Daemon("Signal Handler")
00235 {
00236
00237 boost::mutex::scoped_lock scopedLock(session::Cache::singleton().mutex());
00238 thread= boost::thread(signal_hand);
00239 signal_thread= thread.native_handle();
00240 COND_thread_count.wait(scopedLock);
00241 }
00242
00247 ~SignalHandler()
00248 {
00249
00250
00251
00252
00253 bool completed= false;
00254
00255
00256
00257
00258
00259 uint32_t count= 2;
00260 while (not completed and count--)
00261 {
00262 int error;
00263 int signal= count == 1 ? SIGTSTP : SIGTERM;
00264
00265 if ((error= pthread_kill(thread.native_handle(), signal)))
00266 {
00267 char buffer[1024];
00268 strerror_r(error, buffer, sizeof(buffer));
00269 std::cerr << "pthread_kill() error on shutdown of signal thread (" << buffer << ")\n";
00270 break;
00271 }
00272 else
00273 {
00274 boost::posix_time::milliseconds duration(100);
00275 completed= thread.timed_join(duration);
00276 }
00277 }
00278 }
00279 };
00280
00281 static int init(drizzled::module::Context& context)
00282 {
00283 context.add(new SignalHandler);
00284
00285 return 0;
00286 }
00287
00288
00289 DRIZZLE_DECLARE_PLUGIN
00290 {
00291 DRIZZLE_VERSION_ID,
00292 "signal_handler",
00293 "0.1",
00294 "Brian Aker",
00295 "Default Signal Handler",
00296 PLUGIN_LICENSE_GPL,
00297 init,
00298 NULL,
00299 NULL
00300 }
00301 DRIZZLE_DECLARE_PLUGIN_END;