pidfile.c (51e75198fa09e683bd79de67cb82402373a79b3d) | pidfile.c (412fa8f1145545ad30922007c6cb607d7ddb1003) |
---|---|
1/*- 2 * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 22 unchanged lines hidden (view full) --- 31#include <sys/file.h> 32#include <sys/stat.h> 33 34#include <stdio.h> 35#include <stdlib.h> 36#include <unistd.h> 37#include <fcntl.h> 38#include <string.h> | 1/*- 2 * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 22 unchanged lines hidden (view full) --- 31#include <sys/file.h> 32#include <sys/stat.h> 33 34#include <stdio.h> 35#include <stdlib.h> 36#include <unistd.h> 37#include <fcntl.h> 38#include <string.h> |
39#include <time.h> | |
40#include <err.h> 41#include <errno.h> 42#include <libutil.h> 43 44static int _pidfile_remove(struct pidfh *pfh, int freeit); 45 46static int 47pidfile_verify(struct pidfh *pfh) 48{ 49 struct stat sb; | 39#include <err.h> 40#include <errno.h> 41#include <libutil.h> 42 43static int _pidfile_remove(struct pidfh *pfh, int freeit); 44 45static int 46pidfile_verify(struct pidfh *pfh) 47{ 48 struct stat sb; |
49 int fd; |
|
50 51 if (pfh == NULL || pfh->pf_fd == -1) 52 return (EDOOFUS); 53 /* 54 * Check remembered descriptor. 55 */ 56 if (fstat(pfh->pf_fd, &sb) == -1) 57 return (errno); --- 12 unchanged lines hidden (view full) --- 70 if (fd == -1) 71 return (errno); 72 73 i = read(fd, buf, sizeof(buf) - 1); 74 error = errno; /* Remember errno in case close() wants to change it. */ 75 close(fd); 76 if (i == -1) 77 return (error); | 50 51 if (pfh == NULL || pfh->pf_fd == -1) 52 return (EDOOFUS); 53 /* 54 * Check remembered descriptor. 55 */ 56 if (fstat(pfh->pf_fd, &sb) == -1) 57 return (errno); --- 12 unchanged lines hidden (view full) --- 70 if (fd == -1) 71 return (errno); 72 73 i = read(fd, buf, sizeof(buf) - 1); 74 error = errno; /* Remember errno in case close() wants to change it. */ 75 close(fd); 76 if (i == -1) 77 return (error); |
78 else if (i == 0) 79 return (EAGAIN); | |
80 buf[i] = '\0'; 81 82 *pidptr = strtol(buf, &endptr, 10); 83 if (endptr != &buf[i]) 84 return (EINVAL); 85 86 return (0); 87} 88 89struct pidfh * 90pidfile_open(const char *path, mode_t mode, pid_t *pidptr) 91{ 92 struct pidfh *pfh; 93 struct stat sb; | 78 buf[i] = '\0'; 79 80 *pidptr = strtol(buf, &endptr, 10); 81 if (endptr != &buf[i]) 82 return (EINVAL); 83 84 return (0); 85} 86 87struct pidfh * 88pidfile_open(const char *path, mode_t mode, pid_t *pidptr) 89{ 90 struct pidfh *pfh; 91 struct stat sb; |
94 int error, fd, len, count; 95 struct timespec rqtp; | 92 int error, fd; |
96 97 pfh = malloc(sizeof(*pfh)); 98 if (pfh == NULL) 99 return (NULL); 100 | 93 94 pfh = malloc(sizeof(*pfh)); 95 if (pfh == NULL) 96 return (NULL); 97 |
101 if (path == NULL) 102 len = snprintf(pfh->pf_path, sizeof(pfh->pf_path), 103 "/var/run/%s.pid", getprogname()); 104 else 105 len = snprintf(pfh->pf_path, sizeof(pfh->pf_path), 106 "%s", path); 107 if (len >= (int)sizeof(pfh->pf_path)) { | 98 if (path == NULL) { 99 snprintf(pfh->pf_path, sizeof(pfh->pf_path), "/var/run/%s.pid", 100 getprogname()); 101 } else { 102 strlcpy(pfh->pf_path, path, sizeof(pfh->pf_path)); 103 } 104 if (strlen(pfh->pf_path) == sizeof(pfh->pf_path) - 1) { |
108 free(pfh); 109 errno = ENAMETOOLONG; 110 return (NULL); 111 } 112 113 /* 114 * Open the PID file and obtain exclusive lock. 115 * We truncate PID file here only to remove old PID immediatelly, 116 * PID file will be truncated again in pidfile_write(), so 117 * pidfile_write() can be called multiple times. 118 */ | 105 free(pfh); 106 errno = ENAMETOOLONG; 107 return (NULL); 108 } 109 110 /* 111 * Open the PID file and obtain exclusive lock. 112 * We truncate PID file here only to remove old PID immediatelly, 113 * PID file will be truncated again in pidfile_write(), so 114 * pidfile_write() can be called multiple times. 115 */ |
119 fd = flopen(pfh->pf_path, 120 O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode); | 116 fd = open(pfh->pf_path, 117 O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK, mode); |
121 if (fd == -1) { | 118 if (fd == -1) { |
122 count = 0; 123 rqtp.tv_sec = 0; 124 rqtp.tv_nsec = 5000000; | |
125 if (errno == EWOULDBLOCK && pidptr != NULL) { | 119 if (errno == EWOULDBLOCK && pidptr != NULL) { |
126 again: | |
127 errno = pidfile_read(pfh->pf_path, pidptr); 128 if (errno == 0) 129 errno = EEXIST; | 120 errno = pidfile_read(pfh->pf_path, pidptr); 121 if (errno == 0) 122 errno = EEXIST; |
130 else if (errno == EAGAIN) { 131 if (++count <= 3) { 132 nanosleep(&rqtp, 0); 133 goto again; 134 } 135 } | |
136 } 137 free(pfh); 138 return (NULL); 139 } 140 /* 141 * Remember file information, so in pidfile_write() we are sure we write 142 * to the proper descriptor. 143 */ --- 11 unchanged lines hidden (view full) --- 155 pfh->pf_ino = sb.st_ino; 156 157 return (pfh); 158} 159 160int 161pidfile_write(struct pidfh *pfh) 162{ | 123 } 124 free(pfh); 125 return (NULL); 126 } 127 /* 128 * Remember file information, so in pidfile_write() we are sure we write 129 * to the proper descriptor. 130 */ --- 11 unchanged lines hidden (view full) --- 142 pfh->pf_ino = sb.st_ino; 143 144 return (pfh); 145} 146 147int 148pidfile_write(struct pidfh *pfh) 149{ |
150 struct stat sb; |
|
163 char pidstr[16]; 164 int error, fd; 165 166 /* 167 * Check remembered descriptor, so we don't overwrite some other 168 * file if pidfile was closed and descriptor reused. 169 */ 170 errno = pidfile_verify(pfh); --- 11 unchanged lines hidden (view full) --- 182 if (ftruncate(fd, 0) == -1) { 183 error = errno; 184 _pidfile_remove(pfh, 0); 185 errno = error; 186 return (-1); 187 } 188 189 snprintf(pidstr, sizeof(pidstr), "%u", getpid()); | 151 char pidstr[16]; 152 int error, fd; 153 154 /* 155 * Check remembered descriptor, so we don't overwrite some other 156 * file if pidfile was closed and descriptor reused. 157 */ 158 errno = pidfile_verify(pfh); --- 11 unchanged lines hidden (view full) --- 170 if (ftruncate(fd, 0) == -1) { 171 error = errno; 172 _pidfile_remove(pfh, 0); 173 errno = error; 174 return (-1); 175 } 176 177 snprintf(pidstr, sizeof(pidstr), "%u", getpid()); |
190 if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) { | 178 if (write(fd, pidstr, strlen(pidstr)) != (ssize_t)strlen(pidstr)) { |
191 error = errno; 192 _pidfile_remove(pfh, 0); 193 errno = error; 194 return (-1); 195 } 196 197 return (0); 198} --- 27 unchanged lines hidden (view full) --- 226 error = pidfile_verify(pfh); 227 if (error != 0) { 228 errno = error; 229 return (-1); 230 } 231 232 if (unlink(pfh->pf_path) == -1) 233 error = errno; | 179 error = errno; 180 _pidfile_remove(pfh, 0); 181 errno = error; 182 return (-1); 183 } 184 185 return (0); 186} --- 27 unchanged lines hidden (view full) --- 214 error = pidfile_verify(pfh); 215 if (error != 0) { 216 errno = error; 217 return (-1); 218 } 219 220 if (unlink(pfh->pf_path) == -1) 221 error = errno; |
222 if (flock(pfh->pf_fd, LOCK_UN) == -1) { 223 if (error == 0) 224 error = errno; 225 } |
|
234 if (close(pfh->pf_fd) == -1) { 235 if (error == 0) 236 error = errno; 237 } 238 if (freeit) 239 free(pfh); 240 else 241 pfh->pf_fd = -1; --- 13 unchanged lines hidden --- | 226 if (close(pfh->pf_fd) == -1) { 227 if (error == 0) 228 error = errno; 229 } 230 if (freeit) 231 free(pfh); 232 else 233 pfh->pf_fd = -1; --- 13 unchanged lines hidden --- |