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 }