diff options
Diffstat (limited to 'ndb/src/common/portlib/unix/NdbDaemon.c')
-rw-r--r-- | ndb/src/common/portlib/unix/NdbDaemon.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/ndb/src/common/portlib/unix/NdbDaemon.c b/ndb/src/common/portlib/unix/NdbDaemon.c new file mode 100644 index 00000000000..fc114266c9d --- /dev/null +++ b/ndb/src/common/portlib/unix/NdbDaemon.c @@ -0,0 +1,170 @@ +/* Copyright (C) 2003 MySQL AB + + 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; either version 2 of the License, or + (at your option) any later version. + + 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 "NdbDaemon.h" +#include <assert.h> + +#ifdef NDB_LINUX +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#endif + +#ifdef NDB_SOLARIS +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#endif + +#define NdbDaemon_ErrorSize 500 +#if defined(NDB_LINUX) || defined(NDB_SOLARIS) +long NdbDaemon_DaemonPid; +int NdbDaemon_ErrorCode; +char NdbDaemon_ErrorText[NdbDaemon_ErrorSize]; +#endif +int +NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags) +{ + /* XXX fix other unixes */ +#if defined(NDB_LINUX) || defined(NDB_SOLARIS) + int lockfd = -1, logfd = -1, n; + char buf[64]; + + /* Check that we have write access to lock file */ + assert(lockfile != NULL); + lockfd = open(lockfile, O_CREAT|O_RDWR, 0644); + if (lockfd == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: open for write failed: %s", lockfile, strerror(errno)); + return -1; + } + /* Read any old pid from lock file */ + buf[0] = 0; + n = read(lockfd, buf, sizeof(buf)); + if (n < 0) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: read failed: %s", lockfile, strerror(errno)); + return -1; + } + NdbDaemon_DaemonPid = atol(buf); + if (lseek(lockfd, 0, SEEK_SET) == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: lseek failed: %s", lockfile, strerror(errno)); + return -1; + } + /* Test for lock before becoming daemon */ + if (lockf(lockfd, F_TEST, 0) == -1) { + if (errno == EACCES || errno == EAGAIN) { /* results may vary */ + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: already locked by pid=%ld", lockfile, NdbDaemon_DaemonPid); + return -1; + } + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: lock test failed: %s", lockfile, strerror(errno)); + return -1; + } + /* Test open log file before becoming daemon */ + if (logfile != NULL) { + logfd = open(logfile, O_CREAT|O_WRONLY|O_APPEND, 0644); + if (logfd == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: open for write failed: %s", logfile, strerror(errno)); + return -1; + } + } + /* Fork */ + n = fork(); + if (n == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "fork failed: %s", strerror(errno)); + return -1; + } + /* Exit if we are the parent */ + if (n != 0) { + exit(0); + } + /* Running in child process */ + NdbDaemon_DaemonPid = getpid(); + /* Lock the lock file (likely to succeed due to test above) */ + if (lockf(lockfd, F_LOCK, 0) == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: lock failed: %s", lockfile, strerror(errno)); + return -1; + } + /* Become process group leader */ + if (setsid() == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "setsid failed: %s", strerror(errno)); + return -1; + } + /* Write pid to lock file */ + if (ftruncate(lockfd, 0) == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: ftruncate failed: %s", lockfile, strerror(errno)); + return -1; + } + sprintf(buf, "%ld\n", NdbDaemon_DaemonPid); + n = strlen(buf); + if (write(lockfd, buf, n) != n) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: write failed: %s", lockfile, strerror(errno)); + return -1; + } + /* Do input/output redirections (assume fd 0,1,2 not in use) */ + close(0); + open("/dev/null", O_RDONLY); + if (logfile != 0) { + dup2(logfd, 1); + dup2(logfd, 2); + close(logfd); + } +#endif + /* Success */ + return 0; +} + +#ifdef NDB_DAEMON_TEST + +int +main() +{ + if (NdbDaemon_Make("test.pid", "test.log", 0) == -1) { + fprintf(stderr, "NdbDaemon_Make: %s\n", NdbDaemon_ErrorText); + return 1; + } + sleep(10); + return 0; +} + +#endif |