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