20 #include <my_global.h>
23 #include <ndb_daemon.h>
25 #include <BaseString.hpp>
26 #include <portlib/NdbHost.h>
28 static FILE *dlog_file;
30 static int ERR1(
const char*
fmt, ...)
31 ATTRIBUTE_FORMAT(printf, 1, 2);
33 char ndb_daemon_error[1024];
34 static
int ERR1(const
char* fmt, ...)
37 va_start(argptr, fmt);
38 my_vsnprintf(ndb_daemon_error,
sizeof(ndb_daemon_error),fmt,argptr);
52 static HANDLE g_shutdown_event;
53 static ndb_daemon_stop_t g_stop_func;
54 static ndb_daemon_run_t g_run_func;
56 static void stopper_thread(
void*)
59 WaitForSingleObject(g_shutdown_event, INFINITE);
77 static int service_main(
NTService* service)
80 service->SetRunning();
83 return g_run_func(g_argc, g_argv);
93 is_option(
const char* arg,
const char*
option,
const char** opt_arg)
95 size_t option_len = strlen(option);
96 if (strncmp(arg, option, option_len))
111 install_or_remove_service(
int argc,
char** argv,
112 const char*
name,
const char* display_name)
118 const char* remove_name = NULL;
119 if (is_option(argv[1],
"--remove", &remove_name))
124 name = display_name = remove_name;
126 printf(
"Removing service '%s'\n", display_name);
128 (void)g_ntsvc.
Remove(name);
132 const char* install_name = NULL;
133 if (is_option(argv[1],
"--install", &install_name))
138 name = display_name = install_name;
145 GetModuleFileName(NULL, exe,
sizeof(exe));
146 cmd.
assfmt(
"\"%s\"", exe);
149 cmd.
appfmt(
" \"--service=%s\"", name);
152 for (
int i = 2;
i < argc;
i++)
153 cmd.
appfmt(
" \"%s\"", argv[
i]);
155 printf(
"Installing service '%s' as '%s'\n", display_name, cmd.
c_str());
158 (void)g_ntsvc.
Install(1, name, display_name, cmd.
c_str());
166 int ndb_daemon_init(
int argc,
char** argv,
167 ndb_daemon_run_t
run, ndb_daemon_stop_t stop,
168 const char* name,
const char* display_name)
172 if (install_or_remove_service(argc, argv, name, display_name))
176 const char* service_name = NULL;
178 is_option(argv[1],
"--service", &service_name) &&
183 g_shutdown_event = CreateEvent(0, 0, 0, 0);
186 g_ntsvc.SetShutdownEvent(g_shutdown_event);
195 uintptr_t stop_thread = _beginthread(stopper_thread,0,0);
197 return ERR1(
"couldn't start stopper thread");
205 for (
int i = 2;
i < argc;
i++)
212 return g_ntsvc.
Init(service_name, service_main);
218 return run(argc, argv);
225 #include <sys/locking.h>
227 #define F_TLOCK _LK_NBLCK
228 #define F_ULOCK _LK_UNLCK
229 #define F_LOCK _LK_LOCK
231 static inline int lockf(
int fd,
int cmd, off_t len)
233 return _locking(fd, cmd, len);
236 static inline int ftruncate(
int fd, off_t length)
238 return _chsize(fd, length);
241 static inline int unlink(
const char *filename)
243 return _unlink(filename);
247 static const char *g_pidfile_name = 0;
248 static int g_pidfd = -1, g_logfd = -1;
251 check_files(
const char *pidfile_name,
252 const char *logfile_name,
253 int *pidfd_ret,
int *logfd_ret)
258 int logfd = open(logfile_name, O_CREAT | O_WRONLY | O_APPEND, 0644);
260 return ERR1(
"Failed to open logfile '%s' for write, errno: %d",
261 logfile_name, errno);
263 dlog_file = fdopen(logfd,
"a");
269 return ERR1(
"Missing pid file name");
270 int pidfd= open(pidfile_name, O_CREAT | O_RDWR, 0644);
272 return ERR1(
"Failed to open pidfile '%s' for write, errno: %d",
273 pidfile_name, errno);
278 int bytes_read = read(pidfd, buf,
sizeof(buf));
280 return ERR1(
"Failed to read from pidfile '%s', errno: %d",
281 pidfile_name, errno);
283 long currpid= atol(buf);
284 if(lseek(pidfd, 0, SEEK_SET) == -1)
285 return ERR1(
"Failed to lseek pidfile '%s', errno: %d",
286 pidfile_name, errno);
289 if(lockf(pidfd, F_TLOCK, 0) == -1)
291 if(errno == EACCES || errno == EAGAIN)
292 return ERR1(
"Failed to lock pidfile '%s', already locked by "
293 "pid=%ld, errno: %d", pidfile_name, currpid, errno);
295 if(lockf(pidfd, F_ULOCK, 0) == -1)
296 return ERR1(
"Failed to unlock pidfile '%s', errno: %d",
297 pidfile_name, errno);
305 do_files(
const char *pidfile_name,
const char* logfile_name,
int pidfd,
int logfd)
308 if (lockf(pidfd, F_LOCK, 0) == -1)
309 return ERR1(
"Failed to lock pidfile '%s', errno: %d",
310 pidfile_name, errno);
313 if (ftruncate(pidfd, 0) == -1)
314 return ERR1(
"Failed to truncate file '%s', errno: %d",
315 pidfile_name, errno);
318 int length = my_snprintf(buf,
sizeof(buf),
"%ld",
319 (
long)NdbHost_GetProcessId());
320 if (write(pidfd, buf, length) != length)
321 return ERR1(
"Failed to write pid to pidfile '%s', errno: %d",
322 pidfile_name, errno);
326 freopen(logfile_name,
"a+", stdout);
327 freopen(logfile_name,
"a+", stderr);
328 setbuf(stderr, NULL);
332 const char* fname =
"/dev/null";
333 if (open(fname, O_RDONLY) == -1)
334 return ERR1(
"Failed to open '%s', errno: %d", fname, errno);
349 int ndb_daemonize(
const char* pidfile_name,
const char *logfile_name)
351 int pidfd = -1, logfd = -1;
353 if (check_files(pidfile_name, logfile_name, &pidfd, &logfd))
357 pid_t child = fork();
359 return ERR1(
"fork failed, errno: %d, error: %s", errno, strerror(errno));
367 return ERR1(
"Failed to setsid, errno: %d", errno);
371 if (do_files(pidfile_name, logfile_name, pidfd, logfd))
374 g_pidfile_name = pidfile_name;
379 void ndb_daemon_exit(
int status)
388 unlink(g_pidfile_name);
395 if (g_shutdown_event)
407 void ndb_service_print_options(
const char* name)
411 puts(
"The following Windows specific options may be given as "
412 "the first argument:");
413 printf(
" --install[=name]\tInstall %s as service with given "
414 "name(default: %s), \n"
415 "\t\t\tusing the arguments currently given on command line.\n",
417 printf(
" --remove[=name]\tRemove service with name(default: %s)\n",
424 void ndb_service_wait_for_debugger(
int timeout_sec)
427 if(!IsDebuggerPresent())
430 printf(
"Waiting for debugger to attach, pid=%u\n",GetCurrentProcessId());
432 for(i= 0; i < timeout_sec; i++)
435 if(IsDebuggerPresent())
442 printf(
"pid=%u, debugger not attached after %d seconds, resuming\n",GetCurrentProcessId(),