1LOCKFILE_CREATE(3) Linux Programmer's Manual LOCKFILE_CREATE(3)
2
3
4
6 lockfile_create, lockfile_remove, lockfile_touch, lockfile_check - man‐
7 age lockfiles
8
10 #include <lockfile.h>
11
12 cc [ flag ... ] file ... -llockfile [ library ]
13
14 int lockfile_create( const char *lockfile, int retrycnt, int flags );
15 int lockfile_remove( const char *lockfile );
16 int lockfile_touch( const char *lockfile );
17 int lockfile_check( const char *lockfile, int flags );
18
20 The lockfile_create function creates a lockfile in an NFS safe way.
21
22 If flags is set to L_PID then lockfile_create will not only check for
23 an existing lockfile, but it will read the contents as well to see if
24 it contains a process id in ASCII. If so, the lockfile is only valid if
25 that process still exists.
26
27 If the lockfile is on a shared filesystem, it might have been created
28 by a process on a remote host. Thus the process-id checking is useless
29 and the L_PID flag should not be set. In this case, there is no good
30 way to see if a lockfile is stale. Therefore if the lockfile is older
31 then 5 minutes, it will be removed. That is why the lockfile_touch
32 function is provided: while holding the lock, it needs to be refreshed
33 regulary (every minute or so) by calling lockfile_touch () .
34
35 The lockfile_check function checks if a valid lockfile is already
36 present without trying to create a new lockfile.
37
38 Finally the lockfile_remove function removes the lockfile.
39
40
42 lockfile_create returns one of the following status codes:
43
44 #define L_SUCCESS 0 /* Lockfile created */
45 #define L_NAMELEN 1 /* Recipient name too long (> 13 chars) */
46 #define L_TMPLOCK 2 /* Error creating tmp lockfile */
47 #define L_TMPWRITE 3 /* Can't write pid int tmp lockfile */
48 #define L_MAXTRYS 4 /* Failed after max. number of attempts */
49 #define L_ERROR 5 /* Unknown error; check errno */
50
51 lockfile_check returns 0 if a valid lockfile is present. If no lockfile
52 or no valid lockfile is present, -1 is returned.
53
54 lockfile_touch and lockfile_remove return 0 on success. On failure -1
55 is returned and errno is set appropriately. It is not an error to lock‐
56 file_remove() a non-existing lockfile.
57
58
60 The algorithm that is used to create a lockfile in an atomic way, even
61 over NFS, is as follows:
62
63 1 A unique file is created. In printf format, the name of the file
64 is .lk%05d%x%s. The first argument (%05d) is the current process
65 id. The second argument (%x) consists of the 4 minor bits of the
66 value returned by time(2). The last argument is the system host‐
67 name.
68
69
70 2 Then the lockfile is created using link(2). The return value of
71 link is ignored.
72
73
74 3 Now the lockfile is stat()ed. If the stat fails, we go to step
75 6.
76
77
78 4 The stat value of the lockfile is compared with that of the tem‐
79 porary file. If they are the same, we have the lock. The tempo‐
80 rary file is deleted and a value of 0 (success) is returned to
81 the caller.
82
83
84 5 A check is made to see if the existing lockfile is a valid one.
85 If it isn't valid, the stale lockfile is deleted.
86
87
88 6 Before retrying, we sleep for n seconds. n is initially 5 sec‐
89 onds, but after every retry 5 extra seconds is added up to a
90 maximum of 60 seconds (an incremental backoff). Then we go to
91 step 2 up to retries times.
92
93
95 These functions do not lock a file - they generate a lockfile. However
96 in a lot of cases, such as Unix mailboxes, all concerned programs
97 accessing the mailboxes agree on the fact that the presence of <file‐
98 name>.lock means that <filename> is locked.
99
100 If you are using lockfile_create to create a lock on a file that
101 resides on a remote server, and you already have that file open, you
102 need to flush the NFS attribute cache after locking. This is needed to
103 prevent the following scenario:
104
105 o open /var/mail/USERNAME
106 o attributes, such as size, inode, etc are now cached in the kernel!
107 o meanwhile, another remote system appends data to /var/mail/USERNAME
108 o grab lock using lockfile_create()
109 o seek to end of file
110 o write data
111
112 Now the end of the file really isn't the end of the file - the kernel
113 cached the attributes on open, and st_size is not the end of the file
114 anymore. So after locking the file, you need to tell the kernel to
115 flush the NFS file attribute cache.
116
117 The only portable way to do this is the POSIX fcntl() file locking
118 primitives - locking a file using fcntl() has the fortunate side-effect
119 of invalidating the NFS file attribute cache of the kernel.
120
121 lockfile_create() cannot do this for you for two reasons. One, it just
122 creates a lockfile- it doesn't know which file you are actually trying
123 to lock! Two, even if it could deduce the file you're locking from the
124 filename, by just opening and closing it, it would invalidate any
125 existing POSIX locks the program might already have on that file (yes,
126 POSIX locking semantics are insane!).
127
128 So basically what you need to do is something like this:
129
130 fd = open("/var/mail/USER");
131 .. program code ..
132
133 lockfile_create("/var/mail/USER.lock", x, y);
134
135 /* Invalidate NFS attribute cache using POSIX locks */
136 if (lockf(fd, F_TLOCK, 0) == 0) lockf(fd, F_ULOCK, 0);
137
138 You have to be careful with this if you're putting this in an existing
139 program that might already be using fcntl(), flock() or lockf() lock‐
140 ing- you might invalidate existing locks.
141
142
143 There is also a non-portable way. A lot of NFS operations return the
144 updated attributes - and the Linux kernel actually uses these to update
145 the attribute cache. One of these operations is chmod(2).
146
147 So stat()ing a file and then chmod()ing it to st.st_mode will not actu‐
148 ally change the file, nor will it interfere with any locks on the file,
149 but it will invalidate the attribute cache. The equivalent to use from
150 a shell script would be
151
152 chmod u=u /var/mail/USER
153
154
156 If you are on a system that has a mail spool directory that is only
157 writable by a special group (usually "mail") you cannot create a lock‐
158 file directly in the mailspool directory without special permissions.
159
160 Lockfile_create and lockfile_remove check if the lockfile ends in
161 $USERNAME.lock, and if the directory the lockfile is writable by group
162 "mail". If so, an external set group-id mail executable (dotlockfile(1)
163 ) is spawned to do the actual locking / unlocking.
164
165
167 /usr/lib/liblockfile.so.1
168
169
171 Miquel van Smoorenburg <miquels@cistron.nl>
172
173
175 dotlockfile(1), maillock(3), touchlock (3), mailunlock(3)
176
177
178
179Linux Manpage 04 June 2004 LOCKFILE_CREATE(3)