Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "ink_platform.h"
00025 #include "ink_lockfile.h"
00026
00027 #define LOCKFILE_BUF_LEN 16 // 16 bytes should be enought for a pid
00028
00029 int
00030 Lockfile::Open(pid_t * holding_pid)
00031 {
00032 char buf[LOCKFILE_BUF_LEN];
00033 pid_t val;
00034 int err;
00035 *holding_pid = 0;
00036
00037 #define FAIL(x) \
00038 { \
00039 if (fd > 0) \
00040 close (fd); \
00041 return (x); \
00042 }
00043
00044 struct flock lock;
00045 char *t;
00046 int size;
00047
00048 fd = -1;
00049
00050
00051
00052 do {
00053 fd = open(fname, O_RDWR | O_CREAT, 0644);
00054 } while ((fd < 0) && (errno == EINTR));
00055
00056 if (fd < 0)
00057 return (-errno);
00058
00059
00060
00061 lock.l_type = F_WRLCK;
00062 lock.l_start = 0;
00063 lock.l_whence = SEEK_SET;
00064 lock.l_len = 0;
00065
00066 do {
00067 err = fcntl(fd, F_SETLK, &lock);
00068 } while ((err < 0) && (errno == EINTR));
00069
00070 if (err < 0) {
00071
00072
00073 t = buf;
00074
00075 for (size = 15; size > 0;) {
00076 do {
00077 err = read(fd, t, size);
00078 } while ((err < 0) && (errno == EINTR));
00079
00080 if (err < 0)
00081 FAIL(-errno);
00082 if (err == 0)
00083 break;
00084
00085 size -= err;
00086 t += err;
00087 }
00088
00089 *t = '\0';
00090
00091
00092 if (sscanf(buf, "%d\n", (int*)&val) != 1) {
00093 *holding_pid = 0;
00094 } else {
00095 *holding_pid = val;
00096 }
00097 FAIL(0);
00098 }
00099
00100
00101
00102 do {
00103 err = fcntl(fd, F_GETFD, 0);
00104 } while ((err < 0) && (errno == EINTR));
00105
00106 if (err < 0)
00107 FAIL(-errno);
00108
00109 val = err | FD_CLOEXEC;
00110
00111 do {
00112 err = fcntl(fd, F_SETFD, val);
00113 } while ((err < 0) && (errno == EINTR));
00114
00115 if (err < 0)
00116 FAIL(-errno);
00117
00118
00119
00120
00121 return (1);
00122
00123 #undef FAIL
00124 }
00125
00126 int
00127 Lockfile::Get(pid_t * holding_pid)
00128 {
00129 char buf[LOCKFILE_BUF_LEN];
00130 int err;
00131 *holding_pid = 0;
00132
00133
00134 fd = -1;
00135
00136
00137
00138 err = Open(holding_pid);
00139 if (err != 1)
00140 return err;
00141
00142 if (fd < 0) {
00143 return -1;
00144 }
00145
00146 do {
00147 err = ftruncate(fd, 0);
00148 } while ((err < 0) && (errno == EINTR));
00149
00150 if (err < 0) {
00151 close(fd);
00152 return (-errno);
00153 }
00154
00155 snprintf(buf, sizeof(buf), "%d\n", (int) getpid());
00156
00157 do {
00158 err = write(fd, buf, strlen(buf));
00159 } while ((err < 0) && (errno == EINTR));
00160
00161 if (err != (int) strlen(buf)) {
00162 close(fd);
00163 return (-errno);
00164 }
00165
00166 return (1);
00167 }
00168
00169 void
00170 Lockfile::Close(void)
00171 {
00172 if (fd != -1) {
00173 close(fd);
00174 }
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 static void
00198 lockfile_kill_internal(pid_t init_pid, int init_sig, pid_t pid, const char * , int sig)
00199 {
00200 int err;
00201 int status;
00202
00203 if (init_sig > 0) {
00204 kill(init_pid, init_sig);
00205
00206 do {
00207 err = waitpid(-1, &status, WNOHANG);
00208 if (err == -1) break;
00209 } while(!WIFEXITED(status) && !WIFSIGNALED(status));
00210 }
00211
00212 do {
00213 err = kill(pid, sig);
00214 } while ((err == 0) || ((err < 0) && (errno == EINTR)));
00215
00216 }
00217
00218 void
00219 Lockfile::Kill(int sig, int initial_sig, const char *pname)
00220 {
00221 int err;
00222 int pid;
00223 pid_t holding_pid;
00224
00225 err = Open(&holding_pid);
00226 if (err == 1)
00227 {
00228 Close();
00229 } else if (err == 0)
00230 {
00231 pid = holding_pid;
00232 if (pid != 0) {
00233 lockfile_kill_internal(pid, initial_sig, pid, pname, sig);
00234 }
00235 }
00236 }
00237
00238 void
00239 Lockfile::KillGroup(int sig, int initial_sig, const char *pname)
00240 {
00241 int err;
00242 pid_t pid;
00243 pid_t holding_pid;
00244
00245 err = Open(&holding_pid);
00246 if (err == 1)
00247 {
00248 Close();
00249 } else if (err == 0)
00250 {
00251 do {
00252 pid = getpgid(holding_pid);
00253 } while ((pid < 0) && (errno == EINTR));
00254
00255 if ((pid < 0) || (pid == getpid()))
00256 pid = holding_pid;
00257
00258 if (pid != 0) {
00259
00260 pid = -pid;
00261
00262
00263 lockfile_kill_internal(holding_pid, initial_sig, pid, pname, sig);
00264 }
00265 }
00266 }