Annotation of embedaddon/libpdel/config/app_config_pidfile.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (c) 2001-2002 Packet Design, LLC.
! 4: * All rights reserved.
! 5: *
! 6: * Subject to the following obligations and disclaimer of warranty,
! 7: * use and redistribution of this software, in source or object code
! 8: * forms, with or without modifications are expressly permitted by
! 9: * Packet Design; provided, however, that:
! 10: *
! 11: * (i) Any and all reproductions of the source or object code
! 12: * must include the copyright notice above and the following
! 13: * disclaimer of warranties; and
! 14: * (ii) No rights are granted, in any manner or form, to use
! 15: * Packet Design trademarks, including the mark "PACKET DESIGN"
! 16: * on advertising, endorsements, or otherwise except as such
! 17: * appears in the above copyright notice or in the software.
! 18: *
! 19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
! 20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
! 21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
! 22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
! 23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
! 24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
! 25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
! 26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
! 27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
! 28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
! 29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
! 30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
! 31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
! 32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
! 33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
! 35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
! 36: * THE POSSIBILITY OF SUCH DAMAGE.
! 37: *
! 38: * Author: Archie Cobbs <archie@freebsd.org>
! 39: */
! 40:
! 41: #include <sys/types.h>
! 42: #include <sys/stat.h>
! 43:
! 44: #include <netinet/in.h>
! 45:
! 46: #include <stdio.h>
! 47: #include <assert.h>
! 48: #include <signal.h>
! 49: #include <errno.h>
! 50: #include <syslog.h>
! 51: #include <string.h>
! 52: #include <fcntl.h>
! 53: #include <unistd.h>
! 54: #include <stdarg.h>
! 55:
! 56: #include "structs/structs.h"
! 57: #include "structs/type/array.h"
! 58: #include "util/typed_mem.h"
! 59: #include "config/app_config.h"
! 60: #include "sys/alog.h"
! 61:
! 62: /************************************************************************
! 63: PIDFILE SUBSYSTEM
! 64: ************************************************************************/
! 65:
! 66: static app_ss_startup_t app_pidfile_start;
! 67: static app_ss_shutdown_t app_pidfile_stop;
! 68: static app_ss_willrun_t app_pidfile_willrun;
! 69: static app_ss_changed_t app_pidfile_changed;
! 70:
! 71: static int app_pidfile_fd = -1;
! 72: static int app_pidfile_pid;
! 73:
! 74: const struct app_subsystem app_config_pidfile_subsystem = {
! 75: "pidfile",
! 76: NULL,
! 77: app_pidfile_start,
! 78: app_pidfile_stop,
! 79: app_pidfile_willrun,
! 80: app_pidfile_changed,
! 81: NULL
! 82: };
! 83:
! 84: /*
! 85: * PID file startup
! 86: */
! 87: static int
! 88: app_pidfile_start(struct app_config_ctx *ctx,
! 89: const struct app_subsystem *ss, const void *config)
! 90: {
! 91: const char *const name = ss->arg;
! 92: char *path;
! 93: char buf[32];
! 94:
! 95: /* Get PID file name */
! 96: if ((path = structs_get_string(app_config_get_type(ctx),
! 97: name, config, TYPED_MEM_TEMP)) == NULL) {
! 98: alogf(LOG_ERR, "%s: %m", "structs_get_string");
! 99: return (-1);
! 100: }
! 101:
! 102: /* Create new PID file, or reset old one */
! 103: if (app_pidfile_fd != -1) {
! 104: alog(LOG_DEBUG, "rewriting pidfile \"%s\"", path);
! 105: (void)ftruncate(app_pidfile_fd, 0);
! 106: } else {
! 107: #ifdef O_EXLOCK
! 108: const int flags = O_CREAT|O_WRONLY|O_EXLOCK|O_NONBLOCK;
! 109: #else
! 110: const int flags = O_CREAT|O_WRONLY|O_NONBLOCK;
! 111: #endif
! 112:
! 113: /* Open file */
! 114: alog(LOG_DEBUG, "creating pidfile \"%s\"", path);
! 115: if ((app_pidfile_fd = open(path, flags, 0644)) == -1)
! 116: goto failed;
! 117: #ifdef O_EXLOCK
! 118: goto got_lock;
! 119: #else
! 120: {
! 121: struct flock f;
! 122:
! 123: memset(&f, 0, sizeof(f));
! 124: f.l_pid = getpid();
! 125: f.l_type = F_WRLCK;
! 126: f.l_whence = SEEK_SET;
! 127: if (fcntl(app_pidfile_fd, F_SETLK, &f) != -1)
! 128: goto got_lock;
! 129: }
! 130: #endif
! 131: failed:
! 132: /* Failed to open and lock pidfile */
! 133: switch (errno) {
! 134: case EWOULDBLOCK:
! 135: alog(LOG_ERR, "%s: file locked: exiting", path);
! 136: (void)kill(getpid(), SIGTERM);
! 137: FREE(TYPED_MEM_TEMP, path);
! 138: return (-1);
! 139: default:
! 140: alog(LOG_ERR, "%s: %m", path);
! 141: FREE(TYPED_MEM_TEMP, path);
! 142: return (-1);
! 143: }
! 144: got_lock:
! 145: (void)fcntl(app_pidfile_fd, F_SETFD, 1);
! 146: if (ftruncate(app_pidfile_fd, 0) == -1) {
! 147: alog(LOG_ERR, "%s: can't truncate: %m", path);
! 148: FREE(TYPED_MEM_TEMP, path);
! 149: return (-1);
! 150: }
! 151: }
! 152:
! 153: /* Write PID into file */
! 154: snprintf(buf, sizeof(buf), "%d\n", getpid());
! 155: if (write(app_pidfile_fd, buf, strlen(buf)) != strlen(buf)) {
! 156: alog(LOG_ERR, "%s: write error: %m", path);
! 157: (void)close(app_pidfile_fd);
! 158: app_pidfile_fd = -1;
! 159: FREE(TYPED_MEM_TEMP, path);
! 160: return (-1);
! 161: }
! 162:
! 163: /* Leave file open so it stays locked */
! 164: FREE(TYPED_MEM_TEMP, path);
! 165: app_pidfile_pid = getpid();
! 166: return (0);
! 167: }
! 168:
! 169: /*
! 170: * PID file shutdown
! 171: */
! 172: static void
! 173: app_pidfile_stop(struct app_config_ctx *ctx,
! 174: const struct app_subsystem *ss, const void *config)
! 175: {
! 176: const char *const name = ss->arg;
! 177: char *path;
! 178:
! 179: /* Get PID file name */
! 180: if ((path = structs_get_string(app_config_get_type(ctx),
! 181: name, config, TYPED_MEM_TEMP)) == NULL) {
! 182: alogf(LOG_ERR, "%s: %m", "structs_get_string");
! 183: return;
! 184: }
! 185:
! 186: /* Remove old PID file */
! 187: alog(LOG_DEBUG, "removing pidfile \"%s\"", path);
! 188: (void)unlink(path);
! 189: (void)close(app_pidfile_fd);
! 190: app_pidfile_fd = -1;
! 191: app_pidfile_pid = -1;
! 192: FREE(TYPED_MEM_TEMP, path);
! 193: }
! 194:
! 195: /*
! 196: * PID file necessity check
! 197: */
! 198: static int
! 199: app_pidfile_willrun(struct app_config_ctx *ctx,
! 200: const struct app_subsystem *ss, const void *config)
! 201: {
! 202: const char *const name = ss->arg;
! 203: char *path;
! 204: int r;
! 205:
! 206: /* Get PID file name */
! 207: assert(name != NULL);
! 208: if ((path = structs_get_string(app_config_get_type(ctx),
! 209: name, config, TYPED_MEM_TEMP)) == NULL) {
! 210: alogf(LOG_ERR, "%s: %m", "structs_get_string");
! 211: return (-1);
! 212: }
! 213:
! 214: /* Check if not NULL */
! 215: r = (*path != '\0');
! 216: FREE(TYPED_MEM_TEMP, path);
! 217: return (r);
! 218: }
! 219:
! 220: /*
! 221: * PID file configuration changed check
! 222: */
! 223: static int
! 224: app_pidfile_changed(struct app_config_ctx *ctx,
! 225: const struct app_subsystem *ss, const void *config1,
! 226: const void *config2)
! 227: {
! 228: const char *const name = ss->arg;
! 229: int equal;
! 230:
! 231: /* Compare PID file names as well as PID itself */
! 232: if ((equal = structs_equal(app_config_get_type(ctx),
! 233: name, config1, config2)) == -1) {
! 234: alogf(LOG_ERR, "%s: %m", "structs_equal");
! 235: return (-1);
! 236: }
! 237: return (!equal || getpid() != app_pidfile_pid);
! 238: }
! 239:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>