You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2010/02/15 17:12:30 UTC

svn commit: r910249 - in /commons/sandbox/runtime/trunk/src/main/native: Makefile.in include/acr_pidfile.h os/unix/pidfile.c

Author: mturk
Date: Mon Feb 15 16:12:30 2010
New Revision: 910249

URL: http://svn.apache.org/viewvc?rev=910249&view=rev
Log:
Add pidfile support

Added:
    commons/sandbox/runtime/trunk/src/main/native/include/acr_pidfile.h   (with props)
    commons/sandbox/runtime/trunk/src/main/native/os/unix/pidfile.c   (with props)
Modified:
    commons/sandbox/runtime/trunk/src/main/native/Makefile.in

Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.in
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.in?rev=910249&r1=910248&r2=910249&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/Makefile.in (original)
+++ commons/sandbox/runtime/trunk/src/main/native/Makefile.in Mon Feb 15 16:12:30 2010
@@ -144,6 +144,7 @@
 	$(SRCDIR)/os/unix/mmap.$(OBJ) \
 	$(SRCDIR)/os/unix/mutex.$(OBJ) \
 	$(SRCDIR)/os/unix/path.$(OBJ) \
+	$(SRCDIR)/os/unix/pidfile.$(OBJ) \
 	$(SRCDIR)/os/unix/pipe.$(OBJ) \
 	$(SRCDIR)/os/unix/proc.$(OBJ) \
 	$(SRCDIR)/os/unix/secmem.$(OBJ) \
@@ -186,6 +187,7 @@
 	$(SRCDIR)/os/unix/mmap.$(OBJ) \
 	$(SRCDIR)/os/unix/mutex.$(OBJ) \
 	$(SRCDIR)/os/unix/path.$(OBJ) \
+	$(SRCDIR)/os/unix/pidfile.$(OBJ) \
 	$(SRCDIR)/os/unix/pipe.$(OBJ) \
 	$(SRCDIR)/os/unix/proc.$(OBJ) \
 	$(SRCDIR)/os/unix/secmem.$(OBJ) \
@@ -224,6 +226,7 @@
 	$(SRCDIR)/os/unix/memalign.$(OBJ) \
 	$(SRCDIR)/os/unix/mmap.$(OBJ) \
 	$(SRCDIR)/os/unix/path.$(OBJ) \
+	$(SRCDIR)/os/unix/pidfile.$(OBJ) \
 	$(SRCDIR)/os/unix/pipe.$(OBJ) \
 	$(SRCDIR)/os/unix/proc.$(OBJ) \
 	$(SRCDIR)/os/unix/secmem.$(OBJ) \
@@ -265,6 +268,7 @@
 	$(SRCDIR)/os/unix/mmap.$(OBJ) \
 	$(SRCDIR)/os/unix/mutex.$(OBJ) \
 	$(SRCDIR)/os/unix/path.$(OBJ) \
+	$(SRCDIR)/os/unix/pidfile.$(OBJ) \
 	$(SRCDIR)/os/unix/pipe.$(OBJ) \
 	$(SRCDIR)/os/unix/proc.$(OBJ) \
 	$(SRCDIR)/os/unix/secmem.$(OBJ) \

Added: commons/sandbox/runtime/trunk/src/main/native/include/acr_pidfile.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_pidfile.h?rev=910249&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr_pidfile.h (added)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr_pidfile.h Mon Feb 15 16:12:30 2010
@@ -0,0 +1,81 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ACR_PIDFILE_H
+#define _ACR_PIDFILE_H
+
+#include "acr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file acr_pidfile.h
+ * @brief
+ *
+ * ACR pidfile functions
+ *
+ */
+
+/**
+ * Platform specific pidfile structure
+ */
+typedef struct acr_pidfile_t    acr_pidfile_t;
+
+/**
+ * Create new pidfile
+ * @param name Program name.
+ * @param path Optional path. If NULL system default is used
+ * @param mode Open mode flags
+ * @param pid  Optional pointer to the existing pid if pidfile
+ *             alread exists.
+ */
+ACR_DECLARE(acr_pidfile_t *) ACR_PidFileOpen(const acr_pchar_t *name, 
+                                             const acr_pchar_t *path,
+                                             int mode, acr_pid_t *pid);
+/**
+ * Write current process id to the pidfile
+ * @param pfd Pidfile structure to use.
+ * @return Zero on success or ACR error code.
+ */
+ACR_DECLARE(int) ACR_PidFileWrite(acr_pidfile_t *pfh);
+
+/**
+ * Write current process id to the pidfile
+ * @param pfd Pidfile structure to use.
+ * @return Zero on success or ACR error code.
+ */
+ACR_DECLARE(int) ACR_PidFileWrite(acr_pidfile_t *pfh);
+
+/**
+ * Close the pidfile and free allocated resources
+ * @param pfd Pidfile structure to close.
+ */
+ACR_DECLARE(int) ACR_PidFileClose(acr_pidfile_t *pfh);
+
+/**
+ * Remove the pidfile and free allocated resources
+ * @param pfd Pidfile structure to remove.
+ */
+ACR_DECLARE(int) ACR_PidFileClose(acr_pidfile_t *pfh);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ACR_PIDFILE_H */
+

Propchange: commons/sandbox/runtime/trunk/src/main/native/include/acr_pidfile.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/runtime/trunk/src/main/native/os/unix/pidfile.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/pidfile.c?rev=910249&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/pidfile.c (added)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/pidfile.c Mon Feb 15 16:12:30 2010
@@ -0,0 +1,315 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "acr.h"
+#include "acr_private.h"
+#include "acr_arch.h"
+#include "acr_error.h"
+#include "acr_memory.h"
+#include "acr_port.h"
+#include "acr_string.h"
+#include "acr_pidfile.h"
+
+#include <sys/time.h>
+
+/* XXX: Can we presume this on all platforms
+ */
+#define VARRUN  "/var/run/"
+
+struct acr_pidfile_t {
+    int     fd;
+    char    path[PATH_MAX + 1];
+    dev_t   dev;
+    ino_t   ino;
+};
+
+static int _openlk(const char *path, int flags, ...)
+{
+    int fd, operation, serrno, trunc;
+    struct_stat_t sb;
+    struct_stat_t fsb;
+    mode_t mode;
+
+#ifdef O_EXLOCK
+    flags &= ~O_EXLOCK;
+#endif
+
+    mode = 0;
+    if (flags & O_CREAT) {
+        va_list ap;
+
+        va_start(ap, flags);
+        mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */
+        va_end(ap);
+    }
+
+    operation = LOCK_EX;
+    if (flags & O_NONBLOCK)
+        operation |= LOCK_NB;
+
+    trunc = (flags & O_TRUNC);
+    flags &= ~O_TRUNC;
+
+    for (;;) {
+        if ((fd = open(path, flags, mode)) == -1)
+            /* non-existent or no access */
+            return -1;
+        if (flock(fd, operation) == -1) {
+            /* unsupported or interrupted */
+            serrno = errno;
+            (void)close(fd);
+            errno = serrno;
+            return -1;
+        }
+        if (stat(path, &sb) == -1) {
+            /* disappeared from under our feet */
+            (void)close(fd);
+            continue;
+        }
+        if (fstat(fd, &fsb) == -1) {
+            /* can't happen [tm] */
+            serrno = errno;
+            (void)close(fd);
+            errno = serrno;
+            return -1;
+        }
+        if (sb.st_dev != fsb.st_dev ||
+            sb.st_ino != fsb.st_ino) {
+            /* changed under our feet */
+            (void)close(fd);
+            continue;
+        }
+        if (trunc && ftruncate(fd, 0) != 0) {
+            /* can't happen [tm] */
+            serrno = errno;
+            (void)close(fd);
+            errno = serrno;
+            return -1;
+        }
+        return fd;
+    }
+}
+
+static int acr_PidFileRead(const char *path, pid_t *pid)
+{
+    char buf[16], *endptr;
+    int error, fd, i;
+
+    fd = open(path, O_RDONLY);
+    if (fd == -1)
+        return errno;
+
+    i = read(fd, buf, sizeof(buf) - 1);
+    error = errno;    /* Remember errno in case close() wants to change it. */
+    close(fd);
+    if (i == -1)
+        return error;
+    else if (i == 0)
+        return EAGAIN;
+    buf[i] = '\0';
+
+    *pid = (pid_t)strtol(buf, &endptr, 10);
+    if (endptr != &buf[i])
+        return EINVAL;
+
+    return 0;
+}
+
+static int acr_PidFileVerify(acr_pidfile_t *pfh)
+{
+    struct_stat_t sb;
+
+    if (pfh == NULL || pfh->fd == -1)
+        return EINVAL;
+    /*
+     * Check remembered descriptor.
+     */
+    if (fstat(pfh->fd, &sb) == -1)
+        return errno;
+    if (sb.st_dev != pfh->dev || sb.st_ino != pfh->ino)
+        return EBADF;
+    return 0;
+}
+
+static int acr_PidFileRemove(acr_pidfile_t *pfh, int freeit)
+{
+    int error;
+
+    error = acr_PidFileVerify(pfh);
+    if (error != 0) {
+        errno = error;
+        return errno;
+    }
+
+    if (unlink(pfh->path) == -1)
+        error = errno;
+    if (close(pfh->fd) == -1) {
+        if (error == 0)
+            error = errno;
+    }
+    if (freeit)
+        free(pfh);
+    else
+        pfh->fd = -1;
+    if (error != 0) {
+        errno = error;
+        return errno;
+    }
+    return 0;
+}
+
+ACR_DECLARE(acr_pidfile_t *) ACR_PidFileOpen(const char *name, const char *path,
+                                             int omode, pid_t *pid)
+{
+    acr_pidfile_t *pfh;
+    struct_stat_t sb;
+    int error, fd, len, count;
+    mode_t mode = (mode_t)omode;
+    struct timespec rqtp;
+
+    if (name == NULL) {
+        errno = EINVAL;
+        return NULL;
+    }
+    pfh = malloc(sizeof(acr_pidfile_t));
+    if (pfh == NULL)
+        return NULL;
+
+    if (path == NULL)
+        len = snprintf(pfh->path, sizeof(pfh->path),
+                       VARRUN "%s.pid", name);
+    else
+        len = snprintf(pfh->path, sizeof(pfh->path),
+                       "%s/%s.pid", path, name);
+    if (len >= (int)sizeof(pfh->path)) {
+        free(pfh);
+        errno = ENAMETOOLONG;
+        return NULL;
+    }
+
+    /*
+     * Open the PID file and obtain exclusive lock.
+     * We truncate PID file here only to remove old PID immediatelly,
+     * PID file will be truncated again in ACR_PidFileWrite(), so
+     * ACR_PidFileWrite() can be called multiple times.
+     */
+    fd = _openlk(pfh->path, O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode);
+    if (fd == -1) {
+        count = 0;
+        rqtp.tv_sec  = 0;
+        rqtp.tv_nsec = 5000000;
+        if (errno == EWOULDBLOCK && pid != NULL) {
+        again:
+            errno = acr_PidFileRead(pfh->path, pid);
+            if (errno == 0)
+                errno = EEXIST;
+            else if (errno == EAGAIN) {
+                if (++count <= 3) {
+                    /* TODO: Use wait instead sleeping
+                     */
+                    nanosleep(&rqtp, 0);
+                    goto again;
+                }
+            }
+        }
+        free(pfh);
+        return NULL;
+    }
+    /*
+     * Remember file information, so in ACR_PidFileWrite() we are sure we write
+     * to the proper descriptor.
+     */
+    if (fstat(fd, &sb) == -1) {
+        error = errno;
+        unlink(pfh->path);
+        close(fd);
+        free(pfh);
+        errno = error;
+        return NULL;
+    }
+
+    pfh->fd  = fd;
+    pfh->dev = sb.st_dev;
+    pfh->ino = sb.st_ino;
+
+    return pfh;
+}
+
+ACR_DECLARE(int) ACR_PidFileWrite(acr_pidfile_t *pfh)
+{
+    char pidstr[16];
+    int error, fd;
+
+    /*
+     * Check remembered descriptor, so we don't overwrite some other
+     * file if pidfile was closed and descriptor reused.
+     */
+    errno = acr_PidFileVerify(pfh);
+    if (errno != 0) {
+        /*
+         * Don't close descriptor, because we are not sure if it's ours.
+         */
+        return errno;
+    }
+    fd = pfh->fd;
+
+    /*
+     * Truncate PID file, so multiple calls of pidfile_write() are allowed.
+     */
+    if (ftruncate(fd, 0) == -1) {
+        error = errno;
+        acr_PidFileRemove(pfh, 0);
+        errno = error;
+        return errno;
+    }
+
+    snprintf(pidstr, sizeof(pidstr), "%u", getpid());
+    if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
+        error = errno;
+        acr_PidFileRemove(pfh, 0);
+        errno = error;
+        return errno;
+    }
+
+    return 0;
+}
+
+ACR_DECLARE(int) ACR_PidFileClose(acr_pidfile_t *pfh)
+{
+    int error;
+
+    error = acr_PidFileVerify(pfh);
+    if (error != 0) {
+        errno = error;
+        return error;
+    }
+
+    if (close(pfh->fd) == -1)
+        error = errno;
+    free(pfh);
+    if (error != 0) {
+        errno = error;
+        return error;
+    }
+    return 0;
+}
+
+ACR_DECLARE(int) ACR_PidFileRemove(acr_pidfile_t *pfh)
+{
+
+    return acr_PidFileRemove(pfh, 1);
+}
+

Propchange: commons/sandbox/runtime/trunk/src/main/native/os/unix/pidfile.c
------------------------------------------------------------------------------
    svn:eol-style = native