You're here: Snippet Directory » C/C++ (495)
Language:

lockfile

Language: English
Programming Language: C
Published by: dyfet [not registered]
Last Update: 5/15/2006
Views: 141


Description

Lockfiles are commonly used to provide process exclusive access to a "resource" in the filesystem. This is a small and fairly portable function to create and manage UNIX "lock" files such as those used by mgetty to lock devices, mail access .lck files, etc. This is a fairly long snippet in that various "race" conditions can occur in creating a ".lck" and this code deals with them.

Code

1 #include <config.h> 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <fcntl.h> 5 #include <errno.h> 6 #include <sys/stat.h> 7 #include <lockfile.h> 8 9 #ifndef _LOCK_FORMAT 10 #define _LOCK_FORMAT "%010d %s" 11 #endif 12 13 /* A typical lock file contains only a "pid" for the locking process. However, lck files can also 14 * contain an option string following the pid, and this is sometimes used to indicate who "owns" 15 * the lock and why. 16 */ 17 18 int lockfile(const char *fpath, const char *option) 19 { 20 int fd; 21 int status; 22 pid_t pid; 23 time_t now; 24 struct stat ino; 25 26 if(!option) 27 option = ""; 28 29 for(;;) 30 { 31 fd = open(fpath, O_WRONLY | O_CREAT | O_EXCL, 0660); 32 33 /* if nobody has the lock already, we create and own it. */ 34 35 if(fd > 0) 36 { 37 pid = getpid(); 38 sprintf(query, _LOCK_FORMAT, pid, option); 39 write(fd, query, strlen(query)); 40 close(fd); 41 return 0; 42 } 43 44 /* the create can fail either because a lock already exists (perhaps stale) 45 * or because we don't have permission. If not pre-existing, then assume latter. 46 */ 47 48 if(fd < 0 && errno != EEXIST) 49 return -1; 50 51 /* since lock already exists, we must open to see if it's stale (from a dead process). 52 * Its also possible somebody has already removed the lock between the create and 53 * our open attempt. 54 */ 55 56 fd = open(fpath, O_RDONLY); 57 if(fd < 0) 58 { 59 if(errno == ENOENT) 60 continue; 61 return -1; 62 } 63 sleep(2); 64 status = read(fd, query, sizeof(query) - 1); 65 if(status < 1) 66 { 67 close(fd); 68 continue; 69 } 70 71 query[status] = 0; 72 73 /* we use kill to see if the lock process is still alive. If stale, we remove and retry. */ 74 75 pid = atoi(query); 76 if(pid) 77 { 78 if(pid == getpid()) 79 { 80 status = -1; 81 errno = 0; 82 } 83 else 84 status = kill(pid, 0); 85 if(!status || (errno == EPERM)) 86 { 87 close(fd); 88 return pid; 89 } 90 } 91 close(fd); 92 unlink(fpath); 93 } 94 }

No comments avaiable

Add a comment

Name *  

Email (won't be displayed) *    

Website  

Comment *  

Sicherheitscode Security Code *    

RSS