#At file:///home/msvensson/mysql/6.4-wl4804/ based on revid:msvensson@stripped
2912 Magnus Svensson 2009-03-04
WL#4804 Make ndbd's angel portable
- Move the angel code to angel.cpp
added:
storage/ndb/src/kernel/angel.cpp
storage/ndb/src/kernel/angel.hpp
modified:
storage/ndb/src/kernel/CMakeLists.txt
storage/ndb/src/kernel/Makefile.am
storage/ndb/src/kernel/main.cpp
storage/ndb/src/kernel/ndbd.cpp
storage/ndb/src/kernel/ndbd.hpp
per-file messages:
storage/ndb/src/kernel/CMakeLists.txt
Add file angel.cpp
storage/ndb/src/kernel/Makefile.am
Add file angel.cpp
storage/ndb/src/kernel/angel.cpp
New file angel.cpp containing the angel code moved from main.cpp
Rewrite "catchsigs(true)" as 'ignore_signals'
storage/ndb/src/kernel/angel.hpp
New file angel.hpp defining the interface to angel code
storage/ndb/src/kernel/main.cpp
Move all angel code out to angel.cpp
Move the remaining ndbd specific code to ndbd.cpp
storage/ndb/src/kernel/ndbd.cpp
Moved remaining ndbd code to ndbd.cpp
Rewrite 'catchsigs(true)' to always install all signal handlers, add parameter
for "foreground" and don't install SIGTRAP to make it possible to run in debugger
storage/ndb/src/kernel/ndbd.hpp
Add parameter "foreground"
=== modified file 'storage/ndb/src/kernel/CMakeLists.txt'
--- a/storage/ndb/src/kernel/CMakeLists.txt 2009-03-04 13:11:03 +0000
+++ b/storage/ndb/src/kernel/CMakeLists.txt 2009-03-04 14:54:30 +0000
@@ -76,6 +76,7 @@ LINK_LIBRARIES(ndbcmvmi
ADD_EXECUTABLE(ndbd
main.cpp
ndbd.cpp
+ angel.cpp
SimBlockList.cpp
../mgmsrv/ConfigInfo.cpp
../mgmsrv/Config.cpp
=== modified file 'storage/ndb/src/kernel/Makefile.am'
--- a/storage/ndb/src/kernel/Makefile.am 2009-03-04 13:11:03 +0000
+++ b/storage/ndb/src/kernel/Makefile.am 2009-03-04 14:54:30 +0000
@@ -25,8 +25,8 @@ if BUILD_NDBMTD
ndbbin_PROGRAMS += ndbmtd
endif
-ndbd_SOURCES = main.cpp ndbd.cpp SimBlockList.cpp
-ndbmtd_SOURCES = main.cpp ndbd.cpp SimBlockList.cpp
+ndbd_SOURCES = main.cpp ndbd.cpp angel.cpp SimBlockList.cpp
+ndbmtd_SOURCES = main.cpp ndbd.cpp angel.cpp SimBlockList.cpp
include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am
=== added file 'storage/ndb/src/kernel/angel.cpp'
--- a/storage/ndb/src/kernel/angel.cpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/kernel/angel.cpp 2009-03-04 14:54:30 +0000
@@ -0,0 +1,387 @@
+/* Copyright (C) 2003-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+#include <ndb_version.h>
+
+#include "angel.hpp"
+
+#include <NdbConfig.h>
+#include <NdbAutoPtr.hpp>
+#include <NdbDaemon.h>
+
+#include <ConfigRetriever.hpp>
+
+#include <EventLogger.hpp>
+extern EventLogger * g_eventLogger;
+
+#include "vm/SimBlockList.hpp"
+
+
+#define MAX_FAILED_STARTUPS 3
+// Flag set by child through SIGUSR1 to signal a failed startup
+static bool failed_startup_flag=false;
+// Counter for consecutive failed startups
+static Uint32 failed_startups=0;
+
+// child signalling failed restart
+extern "C"
+void
+handler_sigusr1(int signum)
+{
+ if (!failed_startup_flag)
+ {
+ failed_startups++;
+ failed_startup_flag=true;
+ }
+ g_eventLogger->info("Angel received ndbd startup failure count %u.", failed_startups);
+}
+
+
+// These are used already before fork if fetch_configuration() fails
+// (e.g. Unable to alloc node id). Set them to something reasonable.
+FILE *child_info_file_r=stdin;
+FILE *child_info_file_w=stdout;
+
+#include <Properties.hpp>
+
+static int
+insert(const char * pair, Properties & p)
+{
+ BaseString tmp(pair);
+
+ tmp.trim(" \t\n\r");
+ Vector<BaseString> split;
+ tmp.split(split, ":=", 2);
+ if (split.size() != 2)
+ return -1;
+ p.put(split[0].trim().c_str(), split[1].trim().c_str());
+ return 0;
+}
+
+static int
+readChildInfo(Properties &info)
+{
+ fclose(child_info_file_w);
+ char buf[128];
+ while (fgets(buf, sizeof (buf), child_info_file_r))
+ insert(buf, info);
+ fclose(child_info_file_r);
+ return 0;
+}
+
+static bool
+get_int_property(Properties &info,
+ const char *token, Uint32 *int_val)
+{
+ const char *str_val=0;
+ if (!info.get(token, &str_val))
+ return false;
+ char *endptr;
+ long int tmp=strtol(str_val, &endptr, 10);
+ if (str_val == endptr)
+ return false;
+ *int_val=tmp;
+ return true;
+}
+
+int reportShutdown(class Configuration *config, int error_exit, int restart, Uint32 sphase=256)
+{
+ Uint32 error=0, signum=0;
+#ifndef NDB_WIN
+ Properties info;
+ readChildInfo(info);
+
+ get_int_property(info, "signal", &signum);
+ get_int_property(info, "error", &error);
+ get_int_property(info, "sphase", &sphase);
+#endif
+ Uint32 length, theData[25];
+ EventReport *rep=(EventReport *) theData;
+
+ rep->setNodeId(globalData.ownId);
+ if (restart)
+ theData[1]=1 |
+ (globalData.theRestartFlag == initial_state ? 2 : 0) |
+ (config->getInitialStart() ? 4 : 0);
+ else
+ theData[1]=0;
+
+ if (error_exit == 0)
+ {
+ rep->setEventType(NDB_LE_NDBStopCompleted);
+ theData[2]=signum;
+ length=3;
+ } else
+ {
+ rep->setEventType(NDB_LE_NDBStopForced);
+ theData[2]=signum;
+ theData[3]=error;
+ theData[4]=sphase;
+ theData[5]=0; // extra
+ length=6;
+ }
+
+ { // Log event
+ const EventReport * const eventReport=(EventReport *) & theData[0];
+ g_eventLogger->log(eventReport->getEventType(), theData, length,
+ eventReport->getNodeId(), 0);
+ }
+
+ for (unsigned n=0; n < config->m_mgmds.size(); n++)
+ {
+ NdbMgmHandle h=ndb_mgm_create_handle();
+ if (h == 0 ||
+ ndb_mgm_set_connectstring(h, config->m_mgmds[n].c_str()) ||
+ ndb_mgm_connect(h,
+ 1, //no_retries
+ 0, //retry_delay_in_seconds
+ 0 //verbose
+ ))
+ goto handle_error;
+
+ {
+ if (ndb_mgm_report_event(h, theData, length))
+ goto handle_error;
+ }
+ goto do_next;
+
+handle_error:
+ if (h)
+ {
+ BaseString tmp(ndb_mgm_get_latest_error_msg(h));
+ tmp.append(" : ");
+ tmp.append(ndb_mgm_get_latest_error_desc(h));
+ g_eventLogger->warning("Unable to report shutdown reason to %s: %s",
+ config->m_mgmds[n].c_str(), tmp.c_str());
+ } else
+ {
+ g_eventLogger->error("Unable to report shutdown reason to %s",
+ config->m_mgmds[n].c_str());
+ }
+do_next:
+ if (h)
+ {
+ ndb_mgm_disconnect(h);
+ ndb_mgm_destroy_handle(&h);
+ }
+ }
+ return 0;
+}
+
+
+static void
+ignore_signals(void)
+{
+ static const int ignore_list[] = {
+#ifdef SIGBREAK
+ SIGBREAK,
+#endif
+ SIGHUP,
+ SIGINT,
+#if defined SIGPWR
+ SIGPWR,
+#elif defined SIGINFO
+ SIGINFO,
+#endif
+ SIGQUIT,
+ SIGTERM,
+#ifdef SIGTSTP
+ SIGTSTP,
+#endif
+ SIGTTIN,
+ SIGTTOU,
+ SIGABRT,
+ SIGALRM,
+#ifdef SIGBUS
+ SIGBUS,
+#endif
+ SIGFPE,
+ SIGILL,
+#ifdef SIGIO
+ SIGIO,
+#endif
+#ifdef SIGPOLL
+ SIGPOLL,
+#endif
+ SIGSEGV,
+ SIGPIPE,
+#ifdef SIGTRAP
+ SIGTRAP
+#endif
+ };
+
+ for(size_t i = 0; i < sizeof(ignore_list)/sizeof(ignore_list[0]); i++)
+ signal(ignore_list[i], SIG_IGN);
+}
+
+void
+childReportSignal(int signum);
+
+int
+angel_run(const char* connect_str,
+ const char* bind_address,
+ bool initialstart,
+ bool daemon)
+{
+ if (daemon)
+ {
+ // Become a daemon
+ char *lockfile=NdbConfig_PidFileName(globalData.ownId);
+ char *logfile=NdbConfig_StdoutFileName(globalData.ownId);
+ NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile);
+
+#ifndef NDB_WIN32
+ if (NdbDaemon_Make(lockfile, logfile, 0) == -1)
+ {
+ ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl;
+ return 1;
+ }
+#endif
+ }
+
+ signal(SIGUSR1, handler_sigusr1);
+
+ pid_t child= -1;
+ while (true)
+ {
+ // setup reporting between child and parent
+ int filedes[2];
+ if (pipe(filedes))
+ {
+ g_eventLogger->error("pipe() failed with errno=%d (%s)",
+ errno, strerror(errno));
+ return 1;
+ } else
+ {
+ if (!(child_info_file_w=fdopen(filedes[1], "w")))
+ {
+ g_eventLogger->error("fdopen() failed with errno=%d (%s)",
+ errno, strerror(errno));
+ }
+ if (!(child_info_file_r=fdopen(filedes[0], "r")))
+ {
+ g_eventLogger->error("fdopen() failed with errno=%d (%s)",
+ errno, strerror(errno));
+ }
+ }
+
+ if ((child=fork()) <= 0)
+ break; // child or error
+
+ /**
+ * Parent
+ */
+
+ ignore_signals();
+
+ /**
+ * We no longer need the mgm connection in this process
+ * (as we are the angel, not ndb)
+ *
+ * We don't want to purge any allocated resources (nodeid), so
+ * we set that option to false
+ */
+ Configuration* theConfig = globalEmulatorData.theConfiguration;
+ theConfig->closeConfiguration(false);
+
+ int status=0, error_exit=0, signum=0;
+ while (waitpid(child, &status, 0) != child);
+ if (WIFEXITED(status))
+ {
+ switch (WEXITSTATUS(status)) {
+ case NRT_Default:
+ g_eventLogger->info("Angel shutting down");
+ reportShutdown(theConfig, 0, 0);
+ exit(0);
+ break;
+ case NRT_NoStart_Restart:
+ theConfig->setInitialStart(false);
+ globalData.theRestartFlag=initial_state;
+ break;
+ case NRT_NoStart_InitialStart:
+ theConfig->setInitialStart(true);
+ globalData.theRestartFlag=initial_state;
+ break;
+ case NRT_DoStart_InitialStart:
+ theConfig->setInitialStart(true);
+ globalData.theRestartFlag=perform_start;
+ break;
+ default:
+ error_exit=1;
+ if (theConfig->stopOnError())
+ {
+ /**
+ * Error shutdown && stopOnError()
+ */
+ reportShutdown(theConfig, error_exit, 0);
+ exit(0);
+ }
+ // Fall-through
+ case NRT_DoStart_Restart:
+ theConfig->setInitialStart(false);
+ globalData.theRestartFlag=perform_start;
+ break;
+ }
+ } else
+ {
+ error_exit=1;
+ if (WIFSIGNALED(status))
+ {
+ signum=WTERMSIG(status);
+ childReportSignal(signum);
+ } else
+ {
+ signum=127;
+ g_eventLogger->info("Unknown exit reason. Stopped.");
+ }
+ if (theConfig->stopOnError())
+ {
+ /**
+ * Error shutdown && stopOnError()
+ */
+ reportShutdown(theConfig, error_exit, 0);
+ exit(0);
+ }
+ }
+
+ if (!failed_startup_flag)
+ {
+ // Reset the counter for consecutive failed startups
+ failed_startups=0;
+ } else if (failed_startups >= MAX_FAILED_STARTUPS && !theConfig->stopOnError())
+ {
+ /**
+ * Error shutdown && stopOnError()
+ */
+ g_eventLogger->alert("Ndbd has failed %u consecutive startups. "
+ "Not restarting", failed_startups);
+ reportShutdown(theConfig, error_exit, 0);
+ exit(0);
+ }
+ failed_startup_flag=false;
+ reportShutdown(theConfig, error_exit, 1);
+ g_eventLogger->info("Ndb has terminated (pid %d) restarting", child);
+ theConfig->fetch_configuration(connect_str, bind_address);
+ }
+
+ if (child >= 0)
+ g_eventLogger->info("Angel pid: %d ndb pid: %d", getppid(), getpid());
+ else if (child > 0)
+ g_eventLogger->info("Ndb pid: %d", getpid());
+
+ return 0;
+}
=== added file 'storage/ndb/src/kernel/angel.hpp'
--- a/storage/ndb/src/kernel/angel.hpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/kernel/angel.hpp 2009-03-04 14:54:30 +0000
@@ -0,0 +1,23 @@
+/* Copyright (C) 2003-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ANGEL_HPP
+#define ANGEL_HPP
+
+int angel_run(const char* connect_str,
+ const char* bind_address,
+ bool initialstart,
+ bool daemon);
+#endif
=== modified file 'storage/ndb/src/kernel/main.cpp'
--- a/storage/ndb/src/kernel/main.cpp 2009-03-04 13:11:03 +0000
+++ b/storage/ndb/src/kernel/main.cpp 2009-03-04 14:54:30 +0000
@@ -18,6 +18,7 @@
#include <kernel/NodeBitmask.hpp>
#include "ndbd.hpp"
+#include "angel.hpp"
#include "Configuration.hpp"
#include "vm/SimBlockList.hpp"
@@ -34,8 +35,6 @@
#include <EventLogger.hpp>
extern EventLogger * g_eventLogger;
-extern NdbMutex * theShutdownMutex;
-
static int opt_daemon, opt_no_daemon, opt_foreground,
opt_initial, opt_no_start, opt_initialstart, opt_verbose;
static const char* opt_nowait_nodes = 0;
@@ -43,258 +42,6 @@ static const char* opt_bind_address = 0;
extern NdbNodeBitmask g_nowait_nodes;
-void catchsigs(bool ignore); // for process signal handling
-
-#define MAX_FAILED_STARTUPS 3
-// Flag set by child through SIGUSR1 to signal a failed startup
-static bool failed_startup_flag = false;
-// Counter for consecutive failed startups
-static Uint32 failed_startups = 0;
-extern "C" void handler_shutdown(int signum); // for process signal handling
-extern "C" void handler_error(int signum); // for process signal handling
-extern "C" void handler_sigusr1(int signum); // child signalling failed restart
-
-// These are used already before fork if fetch_configuration() fails
-// (e.g. Unable to alloc node id). Set them to something reasonable.
-static FILE *child_info_file_r= stdin;
-static FILE *child_info_file_w= stdout;
-
-static void writeChildInfo(const char *token, int val)
-{
- fprintf(child_info_file_w, "%s=%d\n", token, val);
- fflush(child_info_file_w);
-}
-
-void childReportSignal(int signum)
-{
- writeChildInfo("signal", signum);
-}
-
-void childReportError(int error)
-{
- writeChildInfo("error", error);
-}
-
-void childExit(int code, Uint32 currentStartPhase)
-{
-#ifndef NDB_WIN
- writeChildInfo("sphase", currentStartPhase);
- writeChildInfo("exit", code);
- fprintf(child_info_file_w, "\n");
- fclose(child_info_file_r);
- fclose(child_info_file_w);
- exit(code);
-#else
- {
- Configuration* theConfig = globalEmulatorData.theConfiguration;
- theConfig->closeConfiguration(true);
- switch(code){
- case NRT_Default:
- g_eventLogger->info("Angel shutting down");
- reportShutdown(theConfig, 0, 0, currentStartPhase);
- exit(0);
- break;
- case NRT_NoStart_Restart:
- theConfig->setInitialStart(false);
- globalData.theRestartFlag = initial_state;
- break;
- case NRT_NoStart_InitialStart:
- theConfig->setInitialStart(true);
- globalData.theRestartFlag = initial_state;
- break;
- case NRT_DoStart_InitialStart:
- theConfig->setInitialStart(true);
- globalData.theRestartFlag = perform_start;
- break;
- default:
- if(theConfig->stopOnError()){
- /**
- * Error shutdown && stopOnError()
- */
- reportShutdown(theConfig, 1, 0, currentStartPhase);
- exit(0);
- }
- // Fall-through
- case NRT_DoStart_Restart:
- theConfig->setInitialStart(false);
- globalData.theRestartFlag = perform_start;
- break;
- }
- char buf[80];
- BaseString::snprintf(buf, sizeof(buf), "WIN_NDBD_CFG=%d %d %d",
- theConfig->getInitialStart(),
- globalData.theRestartFlag, globalData.ownId);
- _putenv(buf);
-
- char exe[MAX_PATH];
- GetModuleFileName(0,exe,sizeof(exe));
-
- STARTUPINFO sinfo;
- ZeroMemory(&sinfo, sizeof(sinfo));
- sinfo.cb= sizeof(STARTUPINFO);
- sinfo.dwFlags= STARTF_USESHOWWINDOW;
- sinfo.wShowWindow= SW_HIDE;
-
- PROCESS_INFORMATION pinfo;
- if(reportShutdown(theConfig, 0, 1, currentStartPhase)) {
- g_eventLogger->error("unable to shutdown");
- exit(1);
- }
- g_eventLogger->info("Ndb has terminated. code=%d", code);
- if(code==NRT_NoStart_Restart)
- globalTransporterRegistry.disconnectAll();
- g_eventLogger->info("Ndb has terminated. Restarting");
- if(CreateProcess(exe, GetCommandLine(), NULL, NULL, TRUE, 0, NULL, NULL,
- &sinfo, &pinfo) == 0)
- {
- g_eventLogger->error("Angel was unable to create child ndbd process"
- " error: %d", GetLastError());
- }
- }
-#endif
-}
-
-void childAbort(int code, Uint32 currentStartPhase)
-{
-#ifndef NDB_WIN
- writeChildInfo("sphase", currentStartPhase);
- writeChildInfo("exit", code);
- fprintf(child_info_file_w, "\n");
- fclose(child_info_file_r);
- fclose(child_info_file_w);
-#ifndef NDB_WIN32
- signal(SIGABRT, SIG_DFL);
-#endif
- abort();
-#else
- childExit(code,currentStartPhase);
-#endif
-}
-
-static int insert(const char * pair, Properties & p)
-{
- BaseString tmp(pair);
-
- tmp.trim(" \t\n\r");
- Vector<BaseString> split;
- tmp.split(split, ":=", 2);
- if(split.size() != 2)
- return -1;
- p.put(split[0].trim().c_str(), split[1].trim().c_str());
- return 0;
-}
-
-static int readChildInfo(Properties &info)
-{
- fclose(child_info_file_w);
- char buf[128];
- while (fgets(buf,sizeof(buf),child_info_file_r))
- insert(buf,info);
- fclose(child_info_file_r);
- return 0;
-}
-
-static bool get_int_property(Properties &info,
- const char *token, Uint32 *int_val)
-{
- const char *str_val= 0;
- if (!info.get(token, &str_val))
- return false;
- char *endptr;
- long int tmp= strtol(str_val, &endptr, 10);
- if (str_val == endptr)
- return false;
- *int_val = tmp;
- return true;
-}
-
-int reportShutdown(class Configuration *config, int error_exit, int restart, Uint32 sphase= 256)
-{
- Uint32 error= 0, signum= 0;
-#ifndef NDB_WIN
- Properties info;
- readChildInfo(info);
-
- get_int_property(info, "signal", &signum);
- get_int_property(info, "error", &error);
- get_int_property(info, "sphase", &sphase);
-#endif
- Uint32 length, theData[25];
- EventReport *rep = (EventReport *)theData;
-
- rep->setNodeId(globalData.ownId);
- if (restart)
- theData[1] = 1 |
- (globalData.theRestartFlag == initial_state ? 2 : 0) |
- (config->getInitialStart() ? 4 : 0);
- else
- theData[1] = 0;
-
- if (error_exit == 0)
- {
- rep->setEventType(NDB_LE_NDBStopCompleted);
- theData[2] = signum;
- length = 3;
- }
- else
- {
- rep->setEventType(NDB_LE_NDBStopForced);
- theData[2] = signum;
- theData[3] = error;
- theData[4] = sphase;
- theData[5] = 0; // extra
- length = 6;
- }
-
- { // Log event
- const EventReport * const eventReport = (EventReport *)&theData[0];
- g_eventLogger->log(eventReport->getEventType(), theData, length,
- eventReport->getNodeId(), 0);
- }
-
- for (unsigned n = 0; n < config->m_mgmds.size(); n++)
- {
- NdbMgmHandle h = ndb_mgm_create_handle();
- if (h == 0 ||
- ndb_mgm_set_connectstring(h, config->m_mgmds[n].c_str()) ||
- ndb_mgm_connect(h,
- 1, //no_retries
- 0, //retry_delay_in_seconds
- 0 //verbose
- ))
- goto handle_error;
-
- {
- if (ndb_mgm_report_event(h, theData, length))
- goto handle_error;
- }
- goto do_next;
-
-handle_error:
- if (h)
- {
- BaseString tmp(ndb_mgm_get_latest_error_msg(h));
- tmp.append(" : ");
- tmp.append(ndb_mgm_get_latest_error_desc(h));
- g_eventLogger->warning("Unable to report shutdown reason to %s: %s",
- config->m_mgmds[n].c_str(), tmp.c_str());
- }
- else
- {
- g_eventLogger->error("Unable to report shutdown reason to %s",
- config->m_mgmds[n].c_str());
- }
-do_next:
- if (h)
- {
- ndb_mgm_disconnect(h);
- ndb_mgm_destroy_handle(&h);
- }
- }
- return 0;
-}
-
-
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndbd"),
@@ -434,277 +181,22 @@ int main(int argc, char** argv)
my_setwd(NdbConfig_get_path(0), MYF(0));
- if (opt_daemon) {
- // Become a daemon
- char *lockfile= NdbConfig_PidFileName(globalData.ownId);
- char *logfile= NdbConfig_StdoutFileName(globalData.ownId);
- NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile);
-
-#ifndef NDB_WIN32
- if (NdbDaemon_Make(lockfile, logfile, 0) == -1)
- {
- ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl;
- return 1;
- }
-#endif
- }
-
#ifndef NDB_WIN32
- signal(SIGUSR1, handler_sigusr1);
-
- pid_t child = -1;
- while (!opt_foreground)
+ if (!opt_foreground)
{
- // setup reporting between child and parent
- int filedes[2];
- if (pipe(filedes))
- {
- g_eventLogger->error("pipe() failed with errno=%d (%s)",
- errno, strerror(errno));
+ if (angel_run(opt_connect_str,
+ opt_bind_address,
+ opt_initialstart,
+ opt_daemon))
return 1;
- }
- else
- {
- if (!(child_info_file_w= fdopen(filedes[1],"w")))
- {
- g_eventLogger->error("fdopen() failed with errno=%d (%s)",
- errno, strerror(errno));
- }
- if (!(child_info_file_r= fdopen(filedes[0],"r")))
- {
- g_eventLogger->error("fdopen() failed with errno=%d (%s)",
- errno, strerror(errno));
- }
- }
-
- if ((child = fork()) <= 0)
- break; // child or error
-
- /**
- * Parent
- */
-
- catchsigs(true);
-
- /**
- * We no longer need the mgm connection in this process
- * (as we are the angel, not ndb)
- *
- * We don't want to purge any allocated resources (nodeid), so
- * we set that option to false
- */
- theConfig->closeConfiguration(false);
-
- int status = 0, error_exit = 0, signum = 0;
- while(waitpid(child, &status, 0) != child);
- if(WIFEXITED(status)){
- switch(WEXITSTATUS(status)){
- case NRT_Default:
- g_eventLogger->info("Angel shutting down");
- reportShutdown(theConfig, 0, 0);
- exit(0);
- break;
- case NRT_NoStart_Restart:
- theConfig->setInitialStart(false);
- globalData.theRestartFlag = initial_state;
- break;
- case NRT_NoStart_InitialStart:
- theConfig->setInitialStart(true);
- globalData.theRestartFlag = initial_state;
- break;
- case NRT_DoStart_InitialStart:
- theConfig->setInitialStart(true);
- globalData.theRestartFlag = perform_start;
- break;
- default:
- error_exit = 1;
- if(theConfig->stopOnError()){
- /**
- * Error shutdown && stopOnError()
- */
- reportShutdown(theConfig, error_exit, 0);
- exit(0);
- }
- // Fall-through
- case NRT_DoStart_Restart:
- theConfig->setInitialStart(false);
- globalData.theRestartFlag = perform_start;
- break;
- }
- } else {
- error_exit = 1;
- if (WIFSIGNALED(status))
- {
- signum = WTERMSIG(status);
- childReportSignal(signum);
- }
- else
- {
- signum = 127;
- g_eventLogger->info("Unknown exit reason. Stopped.");
- }
- if(theConfig->stopOnError()){
- /**
- * Error shutdown && stopOnError()
- */
- reportShutdown(theConfig, error_exit, 0);
- exit(0);
- }
- }
-
- if (!failed_startup_flag)
- {
- // Reset the counter for consecutive failed startups
- failed_startups = 0;
- }
- else if (failed_startups >= MAX_FAILED_STARTUPS && !theConfig->stopOnError())
- {
- /**
- * Error shutdown && stopOnError()
- */
- g_eventLogger->alert("Ndbd has failed %u consecutive startups. "
- "Not restarting", failed_startups);
- reportShutdown(theConfig, error_exit, 0);
- exit(0);
- }
- failed_startup_flag = false;
- reportShutdown(theConfig, error_exit, 1);
- g_eventLogger->info("Ndb has terminated (pid %d) restarting", child);
- theConfig->fetch_configuration(opt_connect_str, opt_bind_address);
+ // ndbd continues here
}
-
- if (child >= 0)
- g_eventLogger->info("Angel pid: %d ndb pid: %d", getppid(), getpid());
- else if (child > 0)
- g_eventLogger->info("Ndb pid: %d", getpid());
else
g_eventLogger->info("Ndb started in foreground");
#else
g_eventLogger->info("Ndb started");
#endif
- return ndbd_run();
-}
-
-
-#define handler_register(signum, handler, ignore)\
-{\
- if (ignore) {\
- if(signum != SIGCHLD)\
- signal(signum, SIG_IGN);\
- } else\
- signal(signum, handler);\
-}
-
-void
-catchsigs(bool ignore){
-#if !defined NDB_WIN32
-
- static const int signals_shutdown[] = {
-#ifdef SIGBREAK
- SIGBREAK,
-#endif
- SIGHUP,
- SIGINT,
-#if defined SIGPWR
- SIGPWR,
-#elif defined SIGINFO
- SIGINFO,
-#endif
- SIGQUIT,
- SIGTERM,
-#ifdef SIGTSTP
- SIGTSTP,
-#endif
- SIGTTIN,
- SIGTTOU
- };
-
- static const int signals_error[] = {
- SIGABRT,
- SIGALRM,
-#ifdef SIGBUS
- SIGBUS,
-#endif
- SIGCHLD,
- SIGFPE,
- SIGILL,
-#ifdef SIGIO
- SIGIO,
-#endif
-#ifdef SIGPOLL
- SIGPOLL,
-#endif
- SIGSEGV
- };
-
- static const int signals_ignore[] = {
- SIGPIPE
- };
-
- size_t i;
- for(i = 0; i < sizeof(signals_shutdown)/sizeof(signals_shutdown[0]); i++)
- handler_register(signals_shutdown[i], handler_shutdown, ignore);
- for(i = 0; i < sizeof(signals_error)/sizeof(signals_error[0]); i++)
- handler_register(signals_error[i], handler_error, ignore);
- for(i = 0; i < sizeof(signals_ignore)/sizeof(signals_ignore[0]); i++)
- handler_register(signals_ignore[i], SIG_IGN, ignore);
-#ifdef SIGTRAP
- if (!opt_foreground)
- handler_register(SIGTRAP, handler_error, ignore);
-#endif
-#endif
-}
-
-extern "C"
-void
-handler_shutdown(int signum){
- g_eventLogger->info("Received signal %d. Performing stop.", signum);
- childReportError(0);
- childReportSignal(signum);
- globalData.theRestartFlag = perform_stop;
+ return ndbd_run(opt_foreground);
}
-extern "C"
-void
-handler_error(int signum){
- // only let one thread run shutdown
- static long thread_id= 0;
-
- if (thread_id != 0 && thread_id == my_thread_id())
- {
- // Shutdown thread received signal
-#ifndef NDB_WIN32
- signal(signum, SIG_DFL);
- kill(getpid(), signum);
-#endif
- while(true)
- NdbSleep_MilliSleep(10);
- }
- if(theShutdownMutex && NdbMutex_Trylock(theShutdownMutex) != 0)
- while(true)
- NdbSleep_MilliSleep(10);
- thread_id= my_thread_id();
- g_eventLogger->info("Received signal %d. Running error handler.", signum);
- childReportSignal(signum);
- // restart the system
- char errorData[64], *info= 0;
-#ifdef HAVE_STRSIGNAL
- info= strsignal(signum);
-#endif
- BaseString::snprintf(errorData, sizeof(errorData), "Signal %d received; %s", signum,
- info ? info : "No text for signal available");
- ERROR_SET_SIGNAL(fatal, NDBD_EXIT_OS_SIGNAL_RECEIVED, errorData, __FILE__);
-}
-
-extern "C"
-void
-handler_sigusr1(int signum)
-{
- if (!failed_startup_flag)
- {
- failed_startups++;
- failed_startup_flag = true;
- }
- g_eventLogger->info("Angel received ndbd startup failure count %u.", failed_startups);
-}
=== modified file 'storage/ndb/src/kernel/ndbd.cpp'
--- a/storage/ndb/src/kernel/ndbd.cpp 2009-03-04 13:11:03 +0000
+++ b/storage/ndb/src/kernel/ndbd.cpp 2009-03-04 14:54:30 +0000
@@ -37,7 +37,6 @@
#include <EventLogger.hpp>
extern EventLogger * g_eventLogger;
-
static void
systemInfo(const Configuration & config, const LogLevel & logLevel)
{
@@ -280,11 +279,237 @@ get_multithreaded_config(EmulatorData& e
}
-void catchsigs(bool ignore);
+extern FILE *child_info_file_r;
+extern FILE *child_info_file_w;
+
+static void
+writeChildInfo(const char *token, int val)
+{
+ fprintf(child_info_file_w, "%s=%d\n", token, val);
+ fflush(child_info_file_w);
+}
+
+void
+childReportSignal(int signum)
+{
+ writeChildInfo("signal", signum);
+}
+
+void
+childReportError(int error)
+{
+ writeChildInfo("error", error);
+}
+
+void
+childExit(int code, Uint32 currentStartPhase)
+{
+#ifndef NDB_WIN
+ writeChildInfo("sphase", currentStartPhase);
+ writeChildInfo("exit", code);
+ fprintf(child_info_file_w, "\n");
+ fclose(child_info_file_r);
+ fclose(child_info_file_w);
+ exit(code);
+#else
+ {
+ Configuration* theConfig=globalEmulatorData.theConfiguration;
+ theConfig->closeConfiguration(true);
+ switch (code) {
+ case NRT_Default:
+ g_eventLogger->info("Angel shutting down");
+ reportShutdown(theConfig, 0, 0, currentStartPhase);
+ exit(0);
+ break;
+ case NRT_NoStart_Restart:
+ theConfig->setInitialStart(false);
+ globalData.theRestartFlag=initial_state;
+ break;
+ case NRT_NoStart_InitialStart:
+ theConfig->setInitialStart(true);
+ globalData.theRestartFlag=initial_state;
+ break;
+ case NRT_DoStart_InitialStart:
+ theConfig->setInitialStart(true);
+ globalData.theRestartFlag=perform_start;
+ break;
+ default:
+ if (theConfig->stopOnError())
+ {
+ /**
+ * Error shutdown && stopOnError()
+ */
+ reportShutdown(theConfig, 1, 0, currentStartPhase);
+ exit(0);
+ }
+ // Fall-through
+ case NRT_DoStart_Restart:
+ theConfig->setInitialStart(false);
+ globalData.theRestartFlag=perform_start;
+ break;
+ }
+ char buf[80];
+ BaseString::snprintf(buf, sizeof (buf), "WIN_NDBD_CFG=%d %d %d",
+ theConfig->getInitialStart(),
+ globalData.theRestartFlag, globalData.ownId);
+ _putenv(buf);
+
+ char exe[MAX_PATH];
+ GetModuleFileName(0, exe, sizeof (exe));
+
+ STARTUPINFO sinfo;
+ ZeroMemory(&sinfo, sizeof (sinfo));
+ sinfo.cb=sizeof (STARTUPINFO);
+ sinfo.dwFlags=STARTF_USESHOWWINDOW;
+ sinfo.wShowWindow=SW_HIDE;
+
+ PROCESS_INFORMATION pinfo;
+ if (reportShutdown(theConfig, 0, 1, currentStartPhase))
+ {
+ g_eventLogger->error("unable to shutdown");
+ exit(1);
+ }
+ g_eventLogger->info("Ndb has terminated. code=%d", code);
+ if (code == NRT_NoStart_Restart)
+ globalTransporterRegistry.disconnectAll();
+ g_eventLogger->info("Ndb has terminated. Restarting");
+ if (CreateProcess(exe, GetCommandLine(), NULL, NULL, TRUE, 0, NULL, NULL,
+ &sinfo, &pinfo) == 0)
+ {
+ g_eventLogger->error("Angel was unable to create child ndbd process"
+ " error: %d", GetLastError());
+ }
+ }
+#endif
+}
+
+void
+childAbort(int code, Uint32 currentStartPhase)
+{
+#ifndef NDB_WIN
+ writeChildInfo("sphase", currentStartPhase);
+ writeChildInfo("exit", code);
+ fprintf(child_info_file_w, "\n");
+ fclose(child_info_file_r);
+ fclose(child_info_file_w);
+#ifndef NDB_WIN32
+ signal(SIGABRT, SIG_DFL);
+#endif
+ abort();
+#else
+ childExit(code, currentStartPhase);
+#endif
+}
+
+extern "C"
+void
+handler_shutdown(int signum){
+ g_eventLogger->info("Received signal %d. Performing stop.", signum);
+ childReportError(0);
+ childReportSignal(signum);
+ globalData.theRestartFlag = perform_stop;
+}
+
+extern NdbMutex * theShutdownMutex;
+
+extern "C"
+void
+handler_error(int signum){
+ // only let one thread run shutdown
+ static long thread_id= 0;
+
+ if (thread_id != 0 && thread_id == my_thread_id())
+ {
+ // Shutdown thread received signal
+#ifndef NDB_WIN32
+ signal(signum, SIG_DFL);
+ kill(getpid(), signum);
+#endif
+ while(true)
+ NdbSleep_MilliSleep(10);
+ }
+ if(theShutdownMutex && NdbMutex_Trylock(theShutdownMutex) != 0)
+ while(true)
+ NdbSleep_MilliSleep(10);
+ thread_id= my_thread_id();
+ g_eventLogger->info("Received signal %d. Running error handler.", signum);
+ childReportSignal(signum);
+ // restart the system
+ char errorData[64], *info= 0;
+#ifdef HAVE_STRSIGNAL
+ info= strsignal(signum);
+#endif
+ BaseString::snprintf(errorData, sizeof(errorData), "Signal %d received; %s", signum,
+ info ? info : "No text for signal available");
+ ERROR_SET_SIGNAL(fatal, NDBD_EXIT_OS_SIGNAL_RECEIVED, errorData, __FILE__);
+}
+
+
+static void
+catchsigs(bool foreground){
+#if !defined NDB_WIN32
+
+ static const int signals_shutdown[] = {
+#ifdef SIGBREAK
+ SIGBREAK,
+#endif
+ SIGHUP,
+ SIGINT,
+#if defined SIGPWR
+ SIGPWR,
+#elif defined SIGINFO
+ SIGINFO,
+#endif
+ SIGQUIT,
+ SIGTERM,
+#ifdef SIGTSTP
+ SIGTSTP,
+#endif
+ SIGTTIN,
+ SIGTTOU
+ };
+
+ static const int signals_error[] = {
+ SIGABRT,
+ SIGALRM,
+#ifdef SIGBUS
+ SIGBUS,
+#endif
+ SIGCHLD,
+ SIGFPE,
+ SIGILL,
+#ifdef SIGIO
+ SIGIO,
+#endif
+#ifdef SIGPOLL
+ SIGPOLL,
+#endif
+ SIGSEGV
+ };
+
+ static const int signals_ignore[] = {
+ SIGPIPE
+ };
+
+ size_t i;
+ for(i = 0; i < sizeof(signals_shutdown)/sizeof(signals_shutdown[0]); i++)
+ signal(signals_shutdown[i], handler_shutdown);
+ for(i = 0; i < sizeof(signals_error)/sizeof(signals_error[0]); i++)
+ signal(signals_error[i], handler_error);
+ for(i = 0; i < sizeof(signals_ignore)/sizeof(signals_ignore[0]); i++)
+ signal(signals_ignore[i], SIG_IGN);
+
+#ifdef SIGTRAP
+ if (!foreground)
+ signal(SIGTRAP, handler_error);
+#endif
+
+#endif
+}
int
-ndbd_run(void)
+ndbd_run(bool foreground)
{
if (get_multithreaded_config(globalEmulatorData))
@@ -343,7 +568,7 @@ ndbd_run(void)
status = NdbThread_SetConcurrencyLevel(30);
assert(status == 0);
- catchsigs(false);
+ catchsigs(foreground);
/**
* Do startup
=== modified file 'storage/ndb/src/kernel/ndbd.hpp'
--- a/storage/ndb/src/kernel/ndbd.hpp 2009-03-04 13:11:03 +0000
+++ b/storage/ndb/src/kernel/ndbd.hpp 2009-03-04 14:54:30 +0000
@@ -16,6 +16,6 @@
#ifndef NDBD_HPP
#define NDBD_HPP
-int ndbd_run(void);
+int ndbd_run(bool foreground);
#endif
| Thread |
|---|
| • bzr commit into mysql-5.1-telco-6.4 branch (msvensson:2912) WL#4804 | Magnus Svensson | 4 Mar |