summaryrefslogtreecommitdiff
path: root/storage/ndb/src/common/portlib/NdbDaemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/ndb/src/common/portlib/NdbDaemon.c')
-rw-r--r--storage/ndb/src/common/portlib/NdbDaemon.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/storage/ndb/src/common/portlib/NdbDaemon.c b/storage/ndb/src/common/portlib/NdbDaemon.c
new file mode 100644
index 00000000000..3f1c1998501
--- /dev/null
+++ b/storage/ndb/src/common/portlib/NdbDaemon.c
@@ -0,0 +1,171 @@
+/* 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 <ndb_global.h>
+#include "NdbDaemon.h"
+
+#define NdbDaemon_ErrorSize 500
+long NdbDaemon_DaemonPid = 0;
+int NdbDaemon_ErrorCode = 0;
+char NdbDaemon_ErrorText[NdbDaemon_ErrorSize] = "";
+
+int
+NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags)
+{
+ int lockfd = -1, logfd = -1, n;
+ char buf[64];
+
+ (void)flags; /* remove warning for unused parameter */
+
+ /* 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;
+ }
+#ifdef F_TLOCK
+ /* Test for lock before becoming daemon */
+ if (lockf(lockfd, F_TLOCK, 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;
+ }
+#endif
+ /* 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;
+ }
+ }
+#ifdef F_TLOCK
+ if (lockf(lockfd, F_ULOCK, 0) == -1)
+ {
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: fail to unlock", lockfile);
+ return -1;
+ }
+#endif
+
+ /* 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);
+ }
+ /* Success */
+ return 0;
+}
+
+#if 0
+int
+NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags)
+{
+ /* Fail */
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "Daemon mode not implemented");
+ return -1;
+}
+#endif
+
+#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