List:Commits« Previous MessageNext Message »
From:Magnus Svensson Date:March 4 2009 2:54pm
Subject:bzr commit into mysql-5.1-telco-6.4 branch (msvensson:2912) WL#4804
View as plain text  
#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#4804Magnus Svensson4 Mar