List:Commits« Previous MessageNext Message »
From:Magnus Svensson Date:March 13 2009 2:23pm
Subject:bzr push into mysql-5.1-telco-7.0 branch (msvensson:2940 to 2941)
View as plain text  
 2941 Magnus Svensson	2009-03-13 [merge]
      Merge
      modified:
        storage/ndb/include/portlib/my_daemon.h
        storage/ndb/src/common/portlib/my_daemon.cc
        storage/ndb/src/mgmsrv/MgmtSrvr.hpp
        storage/ndb/src/mgmsrv/main.cpp

 2940 Jonas Oreland	2009-03-13 [merge]
      merge 63 to 64
      modified:
        storage/ndb/test/ndbapi/test_event.cpp
        storage/ndb/test/src/NdbRestarts.cpp

=== modified file 'storage/ndb/include/portlib/my_daemon.h'
--- a/storage/ndb/include/portlib/my_daemon.h	2009-02-24 11:28:08 +0000
+++ b/storage/ndb/include/portlib/my_daemon.h	2009-03-13 09:48:24 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2008 Sun Microsystems
+/* Copyright (C) 2008-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
@@ -16,120 +16,52 @@
 #ifndef MY_DAEMON_H
 #define MY_DAEMON_H
 
-#ifndef DAEMONEXPORT
-#define DAEMONEXPORT extern
-#endif
-
 C_MODE_START
 
+
+typedef int (*my_daemon_run_t)(int, char**);
+typedef void (*my_daemon_stop_t)(void);
+
 /*
-   all functions return 0 for success so the retval can be returned from main()
+  Used from "mini" main to run an application as a
+  service on windows, where the "run" function will be run
+  as a service if first arg is --service=<service_name>.
 
-   to run the daemon, you must provide a struct MY_DAEMON * to my_daemon_run().
-   the two functions in that struct are start() and stop()
+  Defaults to "normal" behaviour which is to call "run" directly
+  with argc/argv
 
-   int start(void*)
-      . this function should do the main work of the daemon
-      . on windows, it is run in a new thread.
-     -- the parameter to start will always be 0.
-     -- the return value of start is ignored
-
-   int stop()
-      . when called, this function must terminate the start() function
-      . usually, start() runs an event loop and setting a global variable
-        to 0 breaks the loop.  stop() should set this variable to 0.
-     --  the return value is ignored
 */
+int my_daemon_init(int argc, char** argv,
+                   my_daemon_run_t run, my_daemon_stop_t stop,
+                   const char* name, const char* display_name);
 
-typedef int (*daemon_start_t)(void *);
-typedef int (*daemon_onstop_t)();
-struct MY_DAEMON {
-  daemon_start_t start;
-  daemon_onstop_t stop;
-};
+/*
+  To be called at the point where an application needs to daemonize
+  itself.
 
-int my_daemon_run(char *name, struct MY_DAEMON*d);
-int my_daemon_files_run(char *name, struct MY_DAEMON*d, char *node_id);
+  The daemonizing will on most platforms do a fork itself as a daemon.
+  I.e fork, setsid, create pidfile, and redirect all output to logfile.
 
-/*
-   if any of the functions in my_daemon return non-zero (failure)
-   then my_daemon_error contains the error message
+  On windows, only create pidfile and redirect.
 */
-extern char my_daemon_error[];
+int my_daemonize(const char* pidfile_name, const char *logfile_name);
 
-/*
-   my_daemon_install() adds a service called [name] which will
-   be called using the command line [cmd]
-   to start a service after installing it, you can use the command line
-    > net start [name]
-*/
-int my_daemon_install(const char *name, const char *cmd);
 
 /*
-   my_daemon_remove() deletes any service called [name]
-*/
-int my_daemon_remove(const char *name);
+  To be called when application should exit.
 
-int maybe_install_or_remove_service(int argc_,char**argv_,char*opts_remove,char*opts_install,char*default_name);
+  Performs an ordered shutdown of service if running as a serevice.
+ */
+void my_daemon_exit(int status);
 
-/*
-   these macros are provided for convenience.  including these macros
-   in your main source file give you standard options for services
-*/
-#define NONE
-#ifdef _WIN32
-#define MY_DAEMON_VARS_PASTE(prefix) \
-  uchar *prefix##remove,*prefix##install,*prefix##service
-#define MY_DAEMON_VARS(prefix) uchar *prefix remove,* install,*prefix service
-#define MY_DAEMON_VARS0 MY_DAEMON_VARS(NONE)
-#define MY_DAEMON_LONG_OPTS(prefix) \
-  {"install", 'i', "Install this program as a service. (must be first argument)", \
-   &prefix install, &prefix install, 0, GET_STR,  OPT_ARG, 0, 0, 0, 0, 0, 0}, \
-  {"remove",  'r', "Remove this program as a service. (must be first argument)", \
-   &prefix remove,  &prefix remove,  0, GET_STR,  OPT_ARG, 0, 0, 0, 0, 0, 0}, \
-  {"service", 's', "Internal use only (for windows service)", \
-   &prefix service, &prefix service, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-
-#else
-#define MY_DAEMON_VARS_PASTE(prefix)
-#define MY_DAEMON_VARS(prefix)
-#define MY_DAEMON_VARS0
-#define MY_DAEMON_LONG_OPTS(prefix)
-#define MY_DAEMON_LONG_OPTS_PASTE(prefix)
-#endif
-/*
-   my_dlog is the log file created in daemon_files()
-*/
-DAEMONEXPORT FILE *my_dlog;
-/*
-  convenience macros -- mainly for debugging a service
-*/
-#define DLOG(x)    do{fprintf(my_dlog,"%s",x);fflush(my_dlog);}while(0)
-#define DLOG1(x,y) do{fprintf(my_dlog,x,y);fflush(my_dlog);}while(0)
 
 /*
-   my_daemon_prefiles() checks that pidname and logname can be created
-   and that pidname can be locked.
-   a non-zero return usually means that the process abort -- can't create
-   necessary files.
-*/
-int my_daemon_prefiles(const char *pidname, const char *logname);
-/*
-   my_daemon_files() opens the files passed in prefiles() and redirects
-   stdout/stderr to the logfile.
-   my_dlog points is the logfile after daemon_files()
-*/
-int my_daemon_files();
-/*
-   my_daemon_closefiles() closes files opened by my_daemon_files()
+   if any of the functions in my_daemon return non-zero (failure)
+   then my_daemon_error contains the error message
 */
-int my_daemon_closefiles();
 
-/*
-   a helper function to turn a --install command line to a
-   --service command line for internal use with MY_DAEMON_LONG_OPTS
-*/
-char *my_daemon_make_svc_cmd(int n, char **v, char *default_name);
+extern char my_daemon_error[];
 
 C_MODE_END
+
 #endif //MY_DAEMON_H

=== modified file 'storage/ndb/src/common/portlib/my_daemon.cc'
--- a/storage/ndb/src/common/portlib/my_daemon.cc	2009-02-26 10:38:16 +0000
+++ b/storage/ndb/src/common/portlib/my_daemon.cc	2009-03-13 09:48:24 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2008 Sun Microsystems
+/* Copyright (C) 2008-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
@@ -20,303 +20,354 @@
 #include <my_global.h>
 #include <my_sys.h>
 #include <m_string.h>
-#define DAEMONEXPORT
 #include <my_daemon.h>
-#include <NdbConfig.h>
 
-#ifdef _WIN32
-#include <nt_servc.h>
-NTService g_ntsvc;
-HANDLE    g_shutdown_evt;
-#endif
+#include <BaseString.hpp>
+
+static FILE *dlog_file;
 
-static char *daemon_name;
-static long daemonpid;
+static int ERR1(const char* fmt, ...)
+  ATTRIBUTE_FORMAT(printf, 1, 2);
 
-#define errorlen 1023
-char my_daemon_error[errorlen+1];
-int ERR1(const char*fmt,...) {
-  va_list argptr;
-  va_start(argptr, fmt);
-  my_snprintf(my_daemon_error,errorlen,fmt,argptr);
+char my_daemon_error[1024];
+static int ERR1(const char* fmt, ...)
+{
+  va_list argptr;
+  va_start(argptr, fmt);
+  my_vsnprintf(my_daemon_error,sizeof(my_daemon_error),fmt,argptr);
   va_end(argptr);
   return 1;
 }
 
-struct MY_DAEMON g_daemon;
 
 #ifdef _WIN32
-static int init();
-static int stopper(void*)
+
+#include <nt_servc.h>
+static NTService g_ntsvc;
+
+static int g_argc;
+static char** g_argv;
+
+static HANDLE g_shutdown_event;
+static my_daemon_stop_t g_stop_func;
+static my_daemon_run_t g_run_func;
+
+
+static void stopper_thread(void*)
 {
-  WaitForSingleObject(g_shutdown_evt,INFINITE);
-  return g_daemon.stop();
+  // Wait forever until the shutdown event is signaled
+  WaitForSingleObject(g_shutdown_event, INFINITE);
+
+  // Call the installed stop callback function
+  g_stop_func();
 }
-#endif
 
-int my_daemon_run(char *name,struct MY_DAEMON*d)
+
+/*
+  This function is called like:
+    <service dipatcher thread>
+       - NTService::ServiceMain
+        - NTService::StartService
+           <new service thread>
+             -service_main
+ and runs the "application" through
+ the installed callback function "g_run_func"
+*/
+
+static int service_main(NTService* service)
 {
-  daemon_name= name;
-  memcpy(&g_daemon,d,sizeof(g_daemon));
-#ifdef _WIN32
-  g_shutdown_evt=CreateEvent(0, 0, 0, 0);
-  g_ntsvc.SetShutdownEvent(g_shutdown_evt);
-  uintptr_t stop_thread= _beginthread((THREAD_FC)stopper,0,0);
-  if(!stop_thread)
-    return ERR1("couldn't start stopper thread\n");
-  if(init())
-    return ERR1("init failed\n");
-#else /* Fork */
-  pid_t n = fork();
-  if(n==-1)
-    return ERR1("fork failed: %s", strerror(errno));
-  /* Exit if we are the parent */
-  if (n != 0)
-    exit(0);
-  g_daemon.start(0);
-#endif
-  return 0;
+  /* Inform SCM that service is running and can be stopped */
+  service->SetRunning();
+
+  /* Run the application with with argc/argv */
+  return g_run_func(g_argc, g_argv);
 }
 
-#ifdef _WIN32
-char *my_daemon_makecmdv(int c, const char **v)
-{
-  char exe[_MAX_PATH + 3], *retval, *strpos;
-  int i= 0, n= 0;
 
-  GetModuleFileName(NULL, exe, sizeof(exe));
-  n= strlen(exe);
-  for (i= 0; i < c; i++)
-    n += strlen(v[i]) + 8;
-  strpos= retval= (char*)my_malloc(n, MY_FAE);
-  strpos += my_snprintf(strpos, n, "\"%s\"", exe);
-  for (i= 0; i < c; i++)
-    strpos += my_snprintf(strpos, n, " \"%s\"", v[i]);
-  return retval;
-}
-
-static int startswith(char*s,char**set)
-{
-  char**item=set;
-  for(;*item;item++)
-    if(!strncmp(*item,s,strlen(*item)))
-      return 1;
-  return 0;
+/*
+  Check if "arg" contains "option", return the
+  options argument in opt_arg(i.e everything after =)
+*/
+
+static bool
+is_option(const char* arg, const char* option, const char** opt_arg)
+{
+  size_t option_len = strlen(option);
+  if (strncmp(arg, option, option_len))
+    return false; // No hit
+
+  // Step forward to the end of --<option>
+  arg+= option_len;
+  if (*arg == '=')
+  {
+    /* Assign opt_arg pointer to first char after = */
+    *opt_arg= arg + 1;
+  }
+  return true;
 }
 
-char *my_daemon_make_svc_cmd(int n, char **v, char *name)
+
+static int
+install_or_remove_service(int argc, char** argv,
+                          const char* name, const char* display_name)
 {
-  char*swi[]= {"--install","-i",0},
-      *swirs[]= {"--remove","-r","--install","-i","--service","-s",0};
-  if(!startswith(v[0],swi))
-    return ERR1("The install option (-i) must be the first argument\n"),0;
-  int i= 0;
-  for(i=1;i<n;i++)
-    if(startswith(v[i],swirs))
-       return ERR1("The install option (-i) must be the only -i or -r"
-                  " on command line\n"),0;
-  size_t opt_size= strlen(name)+16;
-  char*svcopt=(char*)my_malloc(opt_size, MY_FAE);
-  my_snprintf(svcopt,opt_size-1,"--service=%s",name);
-
-  size_t size=sizeof(char*)*(n+2);
-  char**v1= (char**)my_malloc(size, MY_FAE);
-  memset(v1,0,size);
-  i=0;
-  v1[i++]= svcopt;
-
-  int j= 1;
-  for(;j<n&&v[j][0]!='-';j++); // skip through to first option
-  for(;j<n;j++)
-    v1[i++]= v[j];
-  return my_daemon_makecmdv(i, (const char**)v1);
-}
-
-//returns -1: no install/remove, 0: success, +ve error
-int maybe_install_or_remove_service(int argc_,char**argv_,char*opts_remove,char*opts_install,char*default_name)
-{
-  if(argc_<2)
-    return -1;
-  char*svc=default_name,
-      *r[]={"-r","--remove",0},
-      *i[]={"-i","--install",0};
-  if(opts_remove||startswith(argv_[1],r)) {
-    if(opts_remove)
-      svc=(char*)opts_remove;
-    printf("Removing service \"%s\"\n",svc);
-    return my_daemon_remove(svc);
+  if (argc < 2)
+    return 0; // Nothing to do
+
+  /* --remove as first argument on command line */
+  const char* remove_name = NULL;
+  if (is_option(argv[1], "--remove", &remove_name))
+  {
+    if (remove_name)
+    {
+       /* Use the part after = as service name _and_ display name */
+      name = display_name = remove_name;
+    }
+    printf("Removing service '%s'\n", display_name);
+    /* Remove service. Ignore return value, error is printed to stdout */
+    (void)g_ntsvc.Remove(name);
+    return 1;
   }
-  if(opts_install||startswith(argv_[1],i)) {
-    char *svc_cmd;
-    if(opts_install)
-      svc=(char*)opts_install;
-    svc_cmd= my_daemon_make_svc_cmd(argc_-1, argv_+1, svc);
-    if(!svc_cmd) {
-      fprintf(stderr, my_daemon_error);
-      return 1;
+
+  const char* install_name = NULL;
+  if (is_option(argv[1], "--install", &install_name))
+  {
+    if (install_name)
+    {
+       /* Use the part after = as service name _and_ display name */
+      name = display_name = install_name;
     }
-    printf("Installing service \"%s\"\n",svc);
-    printf("as \"%s\"\n",svc_cmd);
-    return my_daemon_install(svc, svc_cmd);
+
+    BaseString cmd;
+
+    /* Full path to this binary */
+    char exe[MAX_PATH];
+    GetModuleFileName(NULL, exe, sizeof(exe));
+    cmd.assfmt("\"%s\"", exe);
+
+    /* The option that tells which service is starting  */
+    cmd.appfmt(" \"--service=%s\"", name);
+
+    /* All the args after --install(which must be first) */
+    for (int i = 2; i < argc; i++)
+      cmd.appfmt(" \"%s\"", argv[i]);
+
+    printf("Installing service '%s' as '%s'\n", display_name, cmd.c_str());
+
+     /* Install service. Ignore return value, error is printed to stdout */
+    (void)g_ntsvc.Install(1, name, display_name, cmd.c_str());
+    return 1;
   }
-  return -1;
+  return 0;
 }
+#endif
+
 
-int my_daemon_install(const char *name, const char *cmd)
+int my_daemon_init(int argc, char** argv,
+                   my_daemon_run_t run, my_daemon_stop_t stop,
+                   const char* name, const char* display_name)
 {
-  SC_HANDLE svc= 0, scm= 0;
+#ifdef _WIN32
+  // Check for --install or --remove options
+  if (install_or_remove_service(argc, argv, name, display_name))
+    return 1;
+
+  // Check if first arg is --service -> run as service
+  const char* service_name = NULL;
+  if (argc > 1 &&
+      is_option(argv[1], "--service", &service_name) &&
+     service_name)
+  {
+    // Create the shutdown event that will be signaled
+    // by g_ntsvc if the service is to be stopped
+    g_shutdown_event = CreateEvent(0, 0, 0, 0);
+
+    // Install the shutdown event in g_ntsvc
+    g_ntsvc.SetShutdownEvent(g_shutdown_event);
+
+    // Save the stop function so it can be called
+    // by 'stopper_thread'
+    g_stop_func = stop;
+
+    // Create a thread whose only purpose is to wait for
+    // the shutdown event to be signaled and then call the 'stop'
+    // function
+    uintptr_t stop_thread = _beginthread(stopper_thread,0,0);
+    if(!stop_thread)
+      return ERR1("couldn't start stopper thread");
+
+    // Save the run function so it can be called
+    // by 'service_main'
+    g_run_func = run;
+
+    // Build argv without --service
+    BaseString cmd;
+    for (int i = 2; i < argc; i++)
+      cmd.appfmt(" %s", argv[i]);
+    g_argv = BaseString::argify(argv[0], cmd.c_str());
+    g_argc = argc - 1;
+
+    // Start the service thread and let it run 'service_main'
+    // This call will not return until the service thread returns
+    return g_ntsvc.Init(service_name, service_main);
+  }
+#endif
+
+  // Default behaviour, run the "run" function which
+  // should be the "applications" real main
+  return run(argc, argv);
 
-  if(!g_ntsvc.SeekStatus(name, 1))
-    return ERR1("SeekStatus on %s failed\n", name);
-  if(!(scm= OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE)))
-    return ERR1("Failed to install the service: "
-               "Could not open Service Control Manager.\n");
-  if(!(svc= CreateService(scm, name, name,
-                          SERVICE_ALL_ACCESS,
-                          SERVICE_WIN32_OWN_PROCESS,
-                          (1 ? SERVICE_AUTO_START :
-                          SERVICE_DEMAND_START), SERVICE_ERROR_NORMAL,
-                          cmd, 0, 0, 0, 0, 0)))
-    return CloseServiceHandle(scm),
-           ERR1("Failed to install the service: "
-               "Couldn't create service)\n");
-  printf("Service successfully installed.\n");
-  CloseServiceHandle(svc);
-  CloseServiceHandle(scm);
-  return 0;
 }
-#endif
-static int pidfd, logfd;
-int daemon_closefiles()
+
+
+#ifdef _WIN32
+
+#define F_TLOCK _LK_NBLCK
+#define F_ULOCK _LK_UNLCK
+#define F_LOCK  _LK_LOCK
+
+static inline int lockf(int fd, int cmd, off_t len)
 {
-  close(pidfd);
-  fclose(my_dlog);
-  return 0;
+  return _locking(fd, cmd, len);
 }
 
-static const char *pidfile, *logfile;
-int my_daemon_prefiles(const char *pidfil, const char *logfil)
+static inline int ftruncate(int fd, off_t length)
 {
-  int n;
-  char buf[64];
+  return _chsize(fd, length);
+}
+#endif
+
 
-  my_dlog= 0;
-  pidfile= pidfil;
-  logfile= logfil;
-  pidfd= logfd= -1;
-  /* open log file before becoming daemon */
-  if (logfile != NULL)
+static int
+check_files(const char *pidfile_name,
+            const char *logfile_name,
+            int *pidfd_ret, int *logfd_ret)
+{
+  /* Open log file if any */
+  if (logfile_name)
   {
-    logfd= open(logfile, O_CREAT | O_WRONLY | O_APPEND, 0644);
+    int logfd = open(logfile_name, O_CREAT | O_WRONLY | O_APPEND, 0644);
     if(logfd == -1)
-      return ERR1("%s: open for write failed\n", logfile);
-    my_dlog= fdopen(logfd, "a");
+      return ERR1("Failed to open logfile '%s' for write, errno: %d",
+                logfile_name, errno);
+    dlog_file = fdopen(logfd, "a");
+    *logfd_ret = logfd;
   }
+
   /* Check that we have write access to lock file */
-  assert(pidfile != NULL);
-  pidfd= open(pidfile, O_CREAT | O_RDWR, 0644);
-  if(pidfd == -1)
-    return ERR1("%s: open for write failed\n", pidfile);
+  if (!pidfile_name)
+    return ERR1("Missing pid file name");
+  int pidfd= open(pidfile_name, O_CREAT | O_RDWR, 0644);
+  if (pidfd == -1)
+    return ERR1("Failed to open pidfile '%s' for write, errno: %d",
+                pidfile_name, errno);
+
   /* Read any old pid from lock file */
-  n= read(pidfd, buf, sizeof(buf));
-  if(n < 0)
-    return ERR1("%s: read failed\n", pidfile);
-  buf[n]= 0;
-  daemonpid= atol(buf);
+  char buf[32];
+  int bytes_read = read(pidfd, buf, sizeof(buf));
+  if(bytes_read < 0)
+    return ERR1("Failed to read from pidfile '%s', errno: %d",
+                pidfile_name, errno);
+  buf[bytes_read]= 0;
+  long currpid= atol(buf);
   if(lseek(pidfd, 0, SEEK_SET) == -1)
-    return ERR1("%s: lseek failed\n", pidfile);
-#ifdef __WIN__                  //TODO: add my_lockf.c with these definitions
-#define lockf _locking
-#define F_TLOCK _LK_NBLCK
-#define F_ULOCK _LK_UNLCK
-#define F_LOCK  _LK_LOCK
-#endif
-#ifdef F_TLOCK
-  /* Test for lock before becoming daemon */
+    return ERR1("Failed to lseek pidfile '%s', errno: %d",
+                pidfile_name, errno);
+
+  /* Check that file can be locked */
   if(lockf(pidfd, F_TLOCK, 0) == -1)
+  {
     if(errno == EACCES || errno == EAGAIN)
-      return ERR1("pidfile: already locked by pid=%ld\n", daemonpid);
+      return ERR1("Failed to lock pidfile '%s', already locked by "
+                  "pid=%ld, errno: %d", pidfile_name, currpid, errno);
+  }
   if(lockf(pidfd, F_ULOCK, 0) == -1)
-    return ERR1("%s: fail to unlock\n", pidfile);
-#endif
+    return ERR1("Failed to unlock pidfile '%s', errno: %d",
+                pidfile_name, errno);
+
+  *pidfd_ret = pidfd;
   return 0;
 }
 
-int my_daemon_files()
+
+static int
+do_files(const char *pidfile_name, int pidfd, int logfd)
 {
-  int n;
-  char buf[64];
-  /* Running in child process */
-  daemonpid= getpid();
-#ifdef F_TLOCK
-  /* Lock the lock file (likely to succeed due to test above) */
-  if(lockf(pidfd, F_LOCK, 0) == -1)
-    return ERR1("%s: lock failed\n", pidfile);
-#endif
-#ifndef _WIN32
-  /* Become process group leader */
-  if(setsid()==-1)
-    return ERR1("setsid failed\n");
-#endif
+  /* Lock the lock file */
+  if (lockf(pidfd, F_LOCK, 0) == -1)
+    return ERR1("Failed to lock pidfile '%s', errno: %d",
+                pidfile_name, errno);
+
   /* Write pid to lock file */
-  if(IF_WIN(_chsize, ftruncate)(pidfd, 0) == -1)
-    return ERR1("%s: ftruncate failed\n", pidfile);
-  n= my_sprintf(buf, (buf, "%ld\n", daemonpid));
-  if(write(pidfd, buf, n) != n)
-    return ERR1("%s: write failed\n", pidfile);
+  if (ftruncate(pidfd, 0) == -1)
+    return ERR1("Failed to truncate file '%s', errno: %d",
+                pidfile_name, errno);
+
+  char buf[32];
+  int length = my_snprintf(buf, sizeof(buf), "%ld", (long)getpid());
+  if (write(pidfd, buf, length) != length)
+    return ERR1("Failed to write pid to pidfile '%s', errno: %d",
+                pidfile_name, errno);
+
   /* Do input/output redirections (assume fd 0,1,2 not in use) */
   close(0);
-  const char* fname=IF_WIN("nul:", "/dev/null");
-  if(open(fname, O_RDONLY)==-1)
-    return ERR1("couldn't open %s\n", fname);
+  const char* fname = IF_WIN("nul:", "/dev/null");
+  if (open(fname, O_RDONLY) == -1)
+    return ERR1("Failed to open '%s', errno: %d", fname, errno);
+
 #ifdef _WIN32 //no stdout/stderr on windows service
-  *stdout= *stderr= *my_dlog;
+  *stdout= *stderr= *dlog_file;
 #else
-  if (logfd != 0)
+  if (logfd != -1)
   {
     dup2(logfd, 1);
     dup2(logfd, 2);
     close(logfd);
-    my_dlog= stdout;
+    dlog_file= stdout;
   }
 #endif
+
   return 0;
 }
 
-#ifdef _WIN32
-HANDLE hExitEvent;
 
-static int evtlog(char *s)
+int my_daemonize(const char* pidfile_name, const char *logfile_name)
 {
-  HANDLE eventsrc;
-  int n= strlen(s);
-  char *msg= (char*)my_malloc(n + 1, MY_FAE);
-  char *ss[]= { msg };
-  my_snprintf(msg, n, "\n\n%s", s);
-  if(!(eventsrc= RegisterEventSource(0, daemon_name)))
-	  return 1;
-  if(!(ReportEvent(eventsrc, EVENTLOG_ERROR_TYPE, 0, 0, 0, 1, 0, (LPCSTR*)ss, 0)))
-	  return 1;
-  if(!(DeregisterEventSource(eventsrc)))
-	  return 1;
-  my_free(msg,MY_FAE);
-  return 0;
-}
+  int pidfd = -1, logfd = -1;
+  if (check_files(pidfile_name, logfile_name, &pidfd, &logfd))
+    return 1;
+
+#ifndef _WIN32
+  pid_t child = fork();
+  if (child == -1)
+    return ERR1("fork failed, errno: %d, error: %s", errno, strerror(errno));
+
+  /* Exit if we are the parent */
+  if (child != 0)
+    exit(0);
+
+  /* Become process group leader */
+  if(setsid() == -1)
+    return ERR1("Failed to setsid, errno: %d", errno);
+
+#endif
+
+  if (do_files(pidfile_name, pidfd, logfd))
+    return 1;
 
-static DWORD WINAPI main_function(LPVOID x)
-{
-  g_ntsvc.SetRunning();
-  g_daemon.start(0);
   return 0;
 }
 
-static int init()
-{
-  return !g_ntsvc.Init(daemon_name,main_function);
-}
 
-int my_daemon_remove(const char *name)
+void my_daemon_exit(int status)
 {
-  return !g_ntsvc.Remove((LPCSTR)name);
-}
+#ifdef _WIN32
+  /*
+    Stop by calling NtService::Stop if running
+     as a service(i.e g_shutdown_event created)
+  */
+  if (g_shutdown_event)
+    g_ntsvc.Stop();
 #endif
+  exit(status);
+}

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp	2009-02-26 14:52:41 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp	2009-03-13 09:48:24 +0000
@@ -132,7 +132,6 @@ public:
     int print_full_config;
     const char* configdir;
     int verbose;
-    MY_DAEMON_VARS0;
     MgmtOpts() : configdir(MYSQLCLUSTERDIR) {};
     int reload;
     int initial;

=== modified file 'storage/ndb/src/mgmsrv/main.cpp'
--- a/storage/ndb/src/mgmsrv/main.cpp	2009-02-24 11:28:08 +0000
+++ b/storage/ndb/src/mgmsrv/main.cpp	2009-03-13 09:48:24 +0000
@@ -86,7 +86,6 @@ static MgmtSrvr::MgmtOpts opts;
 static struct my_option my_long_options[] =
 {
   NDB_STD_OPTS("ndb_mgmd"),
-  MY_DAEMON_LONG_OPTS(opts.)
   { "config-file", 'f', "Specify cluster configuration file",
     (uchar**) &opts.config_filename, (uchar**) &opts.config_filename, 0,
     GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
@@ -153,9 +152,6 @@ static char **defaults_argv;
      if in a windows service, don't want process to exit()
      until cleanup of other threads is done
 */
-#ifdef _WIN32
-extern HANDLE  g_shutdown_evt;
-#endif
 static void mgmd_exit(int result)
 {
   g_eventLogger->close();
@@ -165,30 +161,13 @@ static void mgmd_exit(int result)
 
   ndb_end(opt_ndb_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
 
-#ifdef _WIN32
-  if(opts.service)
-    SetEvent(g_shutdown_evt); // release stopper thread
-  else
-    exit(result);
-#else
-  exit(result);
-#endif
+  my_daemon_exit(result);
 }
 
-int null_printf(const char*s,...)
-{
-  return 0;
-}
-#define DBG IF_WIN(g_eventLogger->debug,null_printf)
 
-int event_loop(void*);
-int start();
-int argc_;char**argv_;
-int main(int argc, char** argv)
+static int mgmd_main(int argc, char** argv)
 {
   NDB_INIT(argv[0]);
-  argc_= argc;
-  argv_= argv;
 
   g_eventLogger->setCategory("MgmSrvr");
 
@@ -202,36 +181,27 @@ int main(int argc, char** argv)
   opt_debug= IF_WIN("d:t:i:F:o,c:\\ndb_mgmd.trace",
                     "d:t:i:F:o,/tmp/ndb_mgmd.trace");
 #endif
+
   if ((ho_error=handle_options(&argc, &argv, my_long_options,
                                ndb_std_get_one_option)))
     mgmd_exit(ho_error);
 
   if (opts.interactive ||
       opts.non_interactive ||
-      opts.print_full_config ||
-      IF_WIN(1,0)) {
+      opts.print_full_config) {
     opts.daemon= 0;
   }
 
 #ifdef _WIN32
-  int r=maybe_install_or_remove_service(argc_,argv_,
-                                 (char*)opts.remove,(char*)opts.install,
-                                       "MySQL Cluster Management Server");
-  if(r!=-1)
-    return r;
 #ifdef _DEBUG
-  /* it is impossible to attach a debugger to a starting service
-  ** so it is necessary to log to a known place to diagnose
-  ** problems.  services don't have a stdout/stderr so the only
-  ** way to write debug info is to a file.
-  ** change this path if you don't have a c:\
-  */
-  if(opts.service) {
-    char *fn= "c:\\ndb_mgmd_debug.log";
-    g_eventLogger->createFileHandler(fn);
-    DBG(NdbConfig_StdoutFileName(0));
-    DBG(NdbConfig_get_path(0));
-  } else
+  if (opts.daemon)
+  {
+    /* Write eventlog output to file for easier debugging */
+    g_eventLogger->createFileHandler("c:\\ndb_mgmd_debug.log");
+    g_eventLogger->info("StdoutFileName: %s", NdbConfig_StdoutFileName(0));
+    g_eventLogger->info("get_path: %s", NdbConfig_get_path(0));
+    g_eventLogger->info("GetCommandLine: %s", GetCommandLine());
+  }
 #endif
 #endif
   /* Output to console initially */
@@ -253,103 +223,92 @@ int main(int argc, char** argv)
 #if !defined NDB_WIN32
   signal(SIGPIPE, SIG_IGN);
 #endif
-  return start();
-}
 
-int daemon_stop()
-{
-  g_StopServer= true;
-  return 0;
-}
+  while (!g_StopServer)
+  {
+    g_eventLogger->info("NDB Cluster Management Server. %s",
+                        NDB_VERSION_STRING);
 
-int start()
-{
-  g_eventLogger->info("NDB Cluster Management Server. %s", NDB_VERSION_STRING);
+    mgm= new MgmtSrvr(opts, opt_connect_str);
+    if (mgm == NULL) {
+      g_eventLogger->critical("Out of memory, couldn't create MgmtSrvr");
+      mgmd_exit(1);
+    }
 
-  mgm= new MgmtSrvr(opts, opt_connect_str);
-  if (mgm == NULL) {
-    DBG("mgm is NULL");
-    g_eventLogger->critical("Out of memory, couldn't create MgmtSrvr");
-    mgmd_exit(1);
-  }
+    /* Init mgm, load or fetch config */
+    if (!mgm->init()) {
+      delete mgm;
+      mgmd_exit(1);
+    }
 
-  /* Init mgm, load or fetch config */
-  if (!mgm->init()) {
-    delete mgm;
-    mgmd_exit(1);
-  }
+    my_setwd(NdbConfig_get_path(0), MYF(0));
 
-  my_setwd(NdbConfig_get_path(0), MYF(0));
-#ifdef _WIN32
-  DBG("cl %s",GetCommandLine());
-#endif
-  if (IF_WIN(opts.service,opts.daemon)) {
-    DBG("service name %s",IF_WIN(opts.service,""));
-    NodeId localNodeId= mgm->getOwnNodeId();
-    if (localNodeId == 0) {
-      g_eventLogger->error("Couldn't get own node id");
+    if (opts.daemon)
+    {
+      NodeId localNodeId= mgm->getOwnNodeId();
+      if (localNodeId == 0) {
+        g_eventLogger->error("Couldn't get own node id");
+        delete mgm;
+        mgmd_exit(1);
+      }
+
+      char *lockfile= NdbConfig_PidFileName(localNodeId);
+      char *logfile=  NdbConfig_StdoutFileName(localNodeId);
+      if (my_daemonize(lockfile, logfile))
+      {
+        g_eventLogger->error("Couldn't start as daemon, error: '%s'",
+                             my_daemon_error);
+        mgmd_exit(1);
+      }
+    }
+
+    /* Start mgm services */
+    if (!mgm->start()) {
       delete mgm;
       mgmd_exit(1);
     }
-    struct MY_DAEMON thedaemon= {event_loop,daemon_stop};
-    char *lockfile= NdbConfig_PidFileName(localNodeId);
-    char *logfile=  NdbConfig_StdoutFileName(localNodeId);
-    DBG("to open %s,%s", lockfile, logfile);
-    if (my_daemon_prefiles(lockfile, logfile)) {
-      g_eventLogger->error("daemon_prefiles %s", my_daemon_error);
-      mgmd_exit(1);
+
+    if (opts.interactive) {
+      int port= mgm->getPort();
+      BaseString con_str;
+      if(opts.bind_address)
+        con_str.appfmt("host=%s:%d", opts.bind_address, port);
+      else
+        con_str.appfmt("localhost:%d", port);
+      Ndb_mgmclient com(con_str.c_str(), 1);
+      while(!g_StopServer){
+        if (!read_and_execute(&com, "ndb_mgm> ", 1))
+          g_StopServer = true;
+      }
     }
-    if(my_daemon_files()) {
-      g_eventLogger->error("daemon_files %s", my_daemon_error);
-      mgmd_exit(1);
+    else {
+      while (!g_StopServer)
+        NdbSleep_MilliSleep(500);
     }
-    return my_daemon_run((char*)IF_WIN(opts.service,0),&thedaemon);
-  }
-#ifdef _WIN32
-  if(opts.daemon) {
-    g_eventLogger->error("no daemon mode on windows, use -i to set up a service.");
-    mgmd_exit(1);
-  }
-#endif
-  return event_loop(0);
-}
 
-int event_loop(void*)
-{
-  if (!mgm->start()) { /* Start mgm services */
+    g_eventLogger->info("Shutting down server...");
     delete mgm;
-    mgmd_exit(1);
-  }
+    g_eventLogger->info("Shutdown complete");
 
-  if(opts.interactive) {
-    int port= mgm->getPort();
-    BaseString con_str;
-    if(opts.bind_address)
-      con_str.appfmt("host=%s:%d", opts.bind_address, port);
-    else
-      con_str.appfmt("localhost:%d", port);
-    Ndb_mgmclient com(con_str.c_str(), 1);
-    while(g_StopServer != true && read_and_execute(&com, "ndb_mgm> ", 1));
-  }
-  else {
-    while(g_StopServer != true) {
-      NdbSleep_MilliSleep(500);
+    if(g_RestartServer){
+      g_eventLogger->info("Restarting server...");
+      g_RestartServer= g_StopServer= false;
     }
   }
 
-  g_eventLogger->info("Shutting down server...");
-  delete mgm;
-  g_eventLogger->info("Shutdown complete");
-
-  if(g_RestartServer){
-    g_eventLogger->info("Restarting server...");
-    g_RestartServer= g_StopServer= false;
-    int ex= start();
-    if(ex)
-      mgmd_exit(ex);
-  }
-
   mgmd_exit(0);
   return 0;
 }
 
+
+static void mgmd_stop(void)
+{
+  g_StopServer= true;
+}
+
+
+int main(int argc, char** argv)
+{
+  return my_daemon_init(argc, argv, mgmd_main, mgmd_stop,
+                        "ndb_mgmd", "MySQL Cluster Management Server");
+}

Thread
bzr push into mysql-5.1-telco-7.0 branch (msvensson:2940 to 2941)Magnus Svensson13 Mar