WvStreams
|
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * Some handy functions to create/remove /var/lock lockfiles. 00006 */ 00007 #include "wvlockdev.h" 00008 #include "wvfile.h" 00009 #include "strutils.h" 00010 #include <signal.h> 00011 #include <string.h> 00012 #include <sys/types.h> 00013 #include <fcntl.h> 00014 #include <sys/stat.h> 00015 #include <errno.h> 00016 00017 WvLockDev::WvLockDev(WvString _devicename) 00018 : devicename(_devicename) 00019 { 00020 const char *p = strrchr(devicename, '/'); 00021 if (p) 00022 p++; 00023 else 00024 p = devicename; 00025 00026 lock_count = 0; 00027 filename = WvString("/var/lock/serial/LCK..%s", p); 00028 } 00029 00030 00031 WvLockDev::~WvLockDev() 00032 { 00033 if (lock_count) 00034 { 00035 lock_count = 1; 00036 unlock(); 00037 } 00038 } 00039 00040 00041 #if USE_LOCKDEV /* use the liblockdev.a locking routines */ 00042 00043 #include <lockdev.h> 00044 00045 bool WvLockDev::lock() 00046 { 00047 if (lock_count) 00048 { 00049 lock_count++; 00050 return true; 00051 } 00052 00053 if (dev_lock(devicename)) 00054 return false; 00055 00056 lock_count++; 00057 return true; 00058 } 00059 00060 00061 void WvLockDev::unlock() 00062 { 00063 if (!lock_count) return; 00064 00065 if (!--lock_count) 00066 dev_unlock(devicename, getpid()); 00067 } 00068 00069 00070 #else /* !USE_LOCKDEV -- implement our own locking routines */ 00071 00072 00073 // note: this function uses the O_EXCL flag to open(), and thus assumes 00074 // that /var/lock is not an NFS-mounted drive (according to the open() man 00075 // page, you need to follow a special procedure to ensure successful NFS 00076 // locking) 00077 // 00078 // Actually there may be other race conditions that we should look into. 00079 bool WvLockDev::lock() 00080 { 00081 pid_t pid; 00082 00083 if (lock_count) 00084 { 00085 lock_count++; 00086 return true; 00087 } 00088 00089 WvFile fd(filename, O_RDWR | O_EXCL | O_CREAT, 0644); 00090 00091 if (fd.isok()) 00092 { 00093 // We made a lock file... 00094 fd.print("%10s\n", getpid()); 00095 } 00096 else if (fd.geterr() == EEXIST) 00097 { 00098 char *inbuf; 00099 00100 // Lock file is already there! Check for staleness... 00101 sleep(1); // preventing race condition... 00102 00103 fd.open(filename, O_RDONLY); 00104 //fprintf(stderr, "ok: %d\n", fd.isok()); 00105 inbuf = trim_string(fd.blocking_getline(-1)); 00106 //fprintf(stderr, "blocking_getline: '%s'\n", inbuf); 00107 00108 if (inbuf) 00109 pid = atoi(inbuf); 00110 else 00111 pid = 0; 00112 00113 //fprintf(stderr, "pid: '%d'\n", pid); 00114 00115 if (pid && pid != -1 && kill(pid, 0) == -1 && errno == ESRCH) 00116 { 00117 // we can create a lockfile now 00118 fd.close(); 00119 if (unlink(filename)) 00120 return false; // cannot remove lockfile 00121 fd.open(filename, O_RDWR | O_EXCL | O_CREAT, 0644); 00122 fd.print("%10s\n", getpid()); 00123 } 00124 else 00125 return false; // device already locked 00126 } 00127 else // some other unexpected error 00128 return false; 00129 00130 lock_count++; 00131 return true; 00132 } 00133 00134 00135 00136 void WvLockDev::unlock() 00137 { 00138 if (!lock_count) return; 00139 00140 if (!--lock_count) 00141 unlink(filename); 00142 } 00143 00144 00145 #endif /* !USE_LOCKDEV */