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