Skip to content

Commit bd107e1

Browse files
committed
Merge branch 'mh/lockfile'
The lockfile API and its users have been cleaned up. * mh/lockfile: (38 commits) lockfile.h: extract new header file for the functions in lockfile.c hold_locked_index(): move from lockfile.c to read-cache.c hold_lock_file_for_append(): restore errno before returning get_locked_file_path(): new function lockfile.c: rename static functions lockfile: rename LOCK_NODEREF to LOCK_NO_DEREF commit_lock_file_to(): refactor a helper out of commit_lock_file() trim_last_path_component(): replace last_path_elm() resolve_symlink(): take a strbuf parameter resolve_symlink(): use a strbuf for internal scratch space lockfile: change lock_file::filename into a strbuf commit_lock_file(): use a strbuf to manage temporary space try_merge_strategy(): use a statically-allocated lock_file object try_merge_strategy(): remove redundant lock_file allocation struct lock_file: declare some fields volatile lockfile: avoid transitory invalid states git_config_set_multivar_in_file(): avoid call to rollback_lock_file() dump_marks(): remove a redundant call to rollback_lock_file() api-lockfile: document edge cases commit_lock_file(): rollback lock file on failure to rename ...
2 parents 7543dea + 697cc8e commit bd107e1

36 files changed

+510
-260
lines changed

Documentation/technical/api-lockfile.txt

Lines changed: 188 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,72 +3,206 @@ lockfile API
33

44
The lockfile API serves two purposes:
55

6-
* Mutual exclusion. When we write out a new index file, first
7-
we create a new file `$GIT_DIR/index.lock`, write the new
8-
contents into it, and rename it to the final destination
9-
`$GIT_DIR/index`. We try to create the `$GIT_DIR/index.lock`
10-
file with O_EXCL so that we can notice and fail when somebody
11-
else is already trying to update the index file.
12-
13-
* Automatic cruft removal. After we create the "lock" file, we
14-
may decide to `die()`, and we would want to make sure that we
15-
remove the file that has not been committed to its final
16-
destination. This is done by remembering the lockfiles we
17-
created in a linked list and cleaning them up from an
18-
`atexit(3)` handler. Outstanding lockfiles are also removed
19-
when the program dies on a signal.
6+
* Mutual exclusion and atomic file updates. When we want to change a
7+
file, we create a lockfile `<filename>.lock`, write the new file
8+
contents into it, and then rename the lockfile to its final
9+
destination `<filename>`. We create the `<filename>.lock` file with
10+
`O_CREAT|O_EXCL` so that we can notice and fail if somebody else has
11+
already locked the file, then atomically rename the lockfile to its
12+
final destination to commit the changes and unlock the file.
13+
14+
* Automatic cruft removal. If the program exits after we lock a file
15+
but before the changes have been committed, we want to make sure
16+
that we remove the lockfile. This is done by remembering the
17+
lockfiles we have created in a linked list and setting up an
18+
`atexit(3)` handler and a signal handler that clean up the
19+
lockfiles. This mechanism ensures that outstanding lockfiles are
20+
cleaned up if the program exits (including when `die()` is called)
21+
or if the program dies on a signal.
22+
23+
Please note that lockfiles only block other writers. Readers do not
24+
block, but they are guaranteed to see either the old contents of the
25+
file or the new contents of the file (assuming that the filesystem
26+
implements `rename(2)` atomically).
27+
28+
29+
Calling sequence
30+
----------------
31+
32+
The caller:
33+
34+
* Allocates a `struct lock_file` either as a static variable or on the
35+
heap, initialized to zeros. Once you use the structure to call the
36+
`hold_lock_file_*` family of functions, it belongs to the lockfile
37+
subsystem and its storage must remain valid throughout the life of
38+
the program (i.e. you cannot use an on-stack variable to hold this
39+
structure).
40+
41+
* Attempts to create a lockfile by passing that variable and the path
42+
of the final destination (e.g. `$GIT_DIR/index`) to
43+
`hold_lock_file_for_update` or `hold_lock_file_for_append`.
44+
45+
* Writes new content for the destination file by writing to the file
46+
descriptor returned by those functions (also available via
47+
`lock->fd`).
48+
49+
When finished writing, the caller can:
50+
51+
* Close the file descriptor and rename the lockfile to its final
52+
destination by calling `commit_lock_file` or `commit_lock_file_to`.
53+
54+
* Close the file descriptor and remove the lockfile by calling
55+
`rollback_lock_file`.
56+
57+
* Close the file descriptor without removing or renaming the lockfile
58+
by calling `close_lock_file`, and later call `commit_lock_file`,
59+
`commit_lock_file_to`, `rollback_lock_file`, or `reopen_lock_file`.
60+
61+
Even after the lockfile is committed or rolled back, the `lock_file`
62+
object must not be freed or altered by the caller. However, it may be
63+
reused; just pass it to another call of `hold_lock_file_for_update` or
64+
`hold_lock_file_for_append`.
65+
66+
If the program exits before you have called one of `commit_lock_file`,
67+
`commit_lock_file_to`, `rollback_lock_file`, or `close_lock_file`, an
68+
`atexit(3)` handler will close and remove the lockfile, rolling back
69+
any uncommitted changes.
70+
71+
If you need to close the file descriptor you obtained from a
72+
`hold_lock_file_*` function yourself, do so by calling
73+
`close_lock_file`. You should never call `close(2)` yourself!
74+
Otherwise the `struct lock_file` structure would still think that the
75+
file descriptor needs to be closed, and a commit or rollback would
76+
result in duplicate calls to `close(2)`. Worse yet, if you `close(2)`
77+
and then later open another file descriptor for a completely different
78+
purpose, then a commit or rollback might close that unrelated file
79+
descriptor.
80+
81+
82+
Error handling
83+
--------------
84+
85+
The `hold_lock_file_*` functions return a file descriptor on success
86+
or -1 on failure (unless `LOCK_DIE_ON_ERROR` is used; see below). On
87+
errors, `errno` describes the reason for failure. Errors can be
88+
reported by passing `errno` to one of the following helper functions:
89+
90+
unable_to_lock_message::
91+
92+
Append an appropriate error message to a `strbuf`.
93+
94+
unable_to_lock_error::
95+
96+
Emit an appropriate error message using `error()`.
97+
98+
unable_to_lock_die::
99+
100+
Emit an appropriate error message and `die()`.
101+
102+
Similarly, `commit_lock_file`, `commit_lock_file_to`, and
103+
`close_lock_file` return 0 on success. On failure they set `errno`
104+
appropriately, do their best to roll back the lockfile, and return -1.
105+
106+
107+
Flags
108+
-----
109+
110+
The following flags can be passed to `hold_lock_file_for_update` or
111+
`hold_lock_file_for_append`:
112+
113+
LOCK_NO_DEREF::
114+
115+
Usually symbolic links in the destination path are resolved
116+
and the lockfile is created by adding ".lock" to the resolved
117+
path. If `LOCK_NO_DEREF` is set, then the lockfile is created
118+
by adding ".lock" to the path argument itself. This option is
119+
used, for example, when locking a symbolic reference, which
120+
for backwards-compatibility reasons can be a symbolic link
121+
containing the name of the referred-to-reference.
122+
123+
LOCK_DIE_ON_ERROR::
124+
125+
If a lock is already taken for the file, `die()` with an error
126+
message. If this option is not specified, trying to lock a
127+
file that is already locked returns -1 to the caller.
20128

21129

22130
The functions
23131
-------------
24132

25133
hold_lock_file_for_update::
26134

27-
Take a pointer to `struct lock_file`, the filename of
28-
the final destination (e.g. `$GIT_DIR/index`) and a flag
29-
`die_on_error`. Attempt to create a lockfile for the
30-
destination and return the file descriptor for writing
31-
to the file. If `die_on_error` flag is true, it dies if
32-
a lock is already taken for the file; otherwise it
33-
returns a negative integer to the caller on failure.
135+
Take a pointer to `struct lock_file`, the path of the file to
136+
be locked (e.g. `$GIT_DIR/index`) and a flags argument (see
137+
above). Attempt to create a lockfile for the destination and
138+
return the file descriptor for writing to the file.
139+
140+
hold_lock_file_for_append::
141+
142+
Like `hold_lock_file_for_update`, but before returning copy
143+
the existing contents of the file (if any) to the lockfile and
144+
position its write pointer at the end of the file.
145+
146+
get_locked_file_path::
147+
148+
Return the path of the file that is locked by the specified
149+
lock_file object. The caller must free the memory.
34150

35151
commit_lock_file::
36152

37-
Take a pointer to the `struct lock_file` initialized
38-
with an earlier call to `hold_lock_file_for_update()`,
39-
close the file descriptor and rename the lockfile to its
40-
final destination. Returns 0 upon success, a negative
41-
value on failure to close(2) or rename(2).
153+
Take a pointer to the `struct lock_file` initialized with an
154+
earlier call to `hold_lock_file_for_update` or
155+
`hold_lock_file_for_append`, close the file descriptor, and
156+
rename the lockfile to its final destination. Return 0 upon
157+
success. On failure, roll back the lock file and return -1,
158+
with `errno` set to the value from the failing call to
159+
`close(2)` or `rename(2)`. It is a bug to call
160+
`commit_lock_file` for a `lock_file` object that is not
161+
currently locked.
162+
163+
commit_lock_file_to::
164+
165+
Like `commit_lock_file()`, except that it takes an explicit
166+
`path` argument to which the lockfile should be renamed. The
167+
`path` must be on the same filesystem as the lock file.
42168

43169
rollback_lock_file::
44170

45-
Take a pointer to the `struct lock_file` initialized
46-
with an earlier call to `hold_lock_file_for_update()`,
47-
close the file descriptor and remove the lockfile.
171+
Take a pointer to the `struct lock_file` initialized with an
172+
earlier call to `hold_lock_file_for_update` or
173+
`hold_lock_file_for_append`, close the file descriptor and
174+
remove the lockfile. It is a NOOP to call
175+
`rollback_lock_file()` for a `lock_file` object that has
176+
already been committed or rolled back.
48177

49178
close_lock_file::
50-
Take a pointer to the `struct lock_file` initialized
51-
with an earlier call to `hold_lock_file_for_update()`,
52-
and close the file descriptor. Returns 0 upon success,
53-
a negative value on failure to close(2).
54-
55-
Because the structure is used in an `atexit(3)` handler, its
56-
storage has to stay throughout the life of the program. It
57-
cannot be an auto variable allocated on the stack.
58-
59-
Call `commit_lock_file()` or `rollback_lock_file()` when you are
60-
done writing to the file descriptor. If you do not call either
61-
and simply `exit(3)` from the program, an `atexit(3)` handler
62-
will close and remove the lockfile.
63-
64-
If you need to close the file descriptor you obtained from
65-
`hold_lock_file_for_update` function yourself, do so by calling
66-
`close_lock_file()`. You should never call `close(2)` yourself!
67-
Otherwise the `struct
68-
lock_file` structure still remembers that the file descriptor
69-
needs to be closed, and a later call to `commit_lock_file()` or
70-
`rollback_lock_file()` will result in duplicate calls to
71-
`close(2)`. Worse yet, if you `close(2)`, open another file
72-
descriptor for completely different purpose, and then call
73-
`commit_lock_file()` or `rollback_lock_file()`, they may close
74-
that unrelated file descriptor.
179+
180+
Take a pointer to the `struct lock_file` initialized with an
181+
earlier call to `hold_lock_file_for_update` or
182+
`hold_lock_file_for_append`, and close the file descriptor.
183+
Return 0 upon success. On failure to `close(2)`, return a
184+
negative value and roll back the lock file. Usually
185+
`commit_lock_file`, `commit_lock_file_to`, or
186+
`rollback_lock_file` should eventually be called if
187+
`close_lock_file` succeeds.
188+
189+
reopen_lock_file::
190+
191+
Re-open a lockfile that has been closed (using
192+
`close_lock_file`) but not yet committed or rolled back. This
193+
can be used to implement a sequence of operations like the
194+
following:
195+
196+
* Lock file.
197+
198+
* Write new contents to lockfile, then `close_lock_file` to
199+
cause the contents to be written to disk.
200+
201+
* Pass the name of the lockfile to another program to allow it
202+
(and nobody else) to inspect the contents you wrote, while
203+
still holding the lock yourself.
204+
205+
* `reopen_lock_file` to reopen the lockfile. Make further
206+
updates to the contents.
207+
208+
* `commit_lock_file` to make the final version permanent.

builtin/add.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
#include "cache.h"
77
#include "builtin.h"
8+
#include "lockfile.h"
89
#include "dir.h"
910
#include "pathspec.h"
1011
#include "exec_cmd.h"

builtin/apply.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*
88
*/
99
#include "cache.h"
10+
#include "lockfile.h"
1011
#include "cache-tree.h"
1112
#include "quote.h"
1213
#include "blob.h"

builtin/checkout-index.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
*/
77
#include "builtin.h"
8-
#include "cache.h"
8+
#include "lockfile.h"
99
#include "quote.h"
1010
#include "cache-tree.h"
1111
#include "parse-options.h"

builtin/checkout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#include "cache.h"
21
#include "builtin.h"
2+
#include "lockfile.h"
33
#include "parse-options.h"
44
#include "refs.h"
55
#include "commit.h"

builtin/clone.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
#include "builtin.h"
12+
#include "lockfile.h"
1213
#include "parse-options.h"
1314
#include "fetch-pack.h"
1415
#include "refs.h"

builtin/commit.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#include "cache.h"
9+
#include "lockfile.h"
910
#include "cache-tree.h"
1011
#include "color.h"
1112
#include "dir.h"
@@ -315,8 +316,8 @@ static void refresh_cache_or_die(int refresh_flags)
315316
die_resolve_conflict("commit");
316317
}
317318

318-
static char *prepare_index(int argc, const char **argv, const char *prefix,
319-
const struct commit *current_head, int is_status)
319+
static const char *prepare_index(int argc, const char **argv, const char *prefix,
320+
const struct commit *current_head, int is_status)
320321
{
321322
struct string_list partial;
322323
struct pathspec pathspec;
@@ -341,7 +342,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
341342
die(_("unable to create temporary index"));
342343

343344
old_index_env = getenv(INDEX_ENVIRONMENT);
344-
setenv(INDEX_ENVIRONMENT, index_lock.filename, 1);
345+
setenv(INDEX_ENVIRONMENT, index_lock.filename.buf, 1);
345346

346347
if (interactive_add(argc, argv, prefix, patch_interactive) != 0)
347348
die(_("interactive add failed"));
@@ -352,7 +353,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
352353
unsetenv(INDEX_ENVIRONMENT);
353354

354355
discard_cache();
355-
read_cache_from(index_lock.filename);
356+
read_cache_from(index_lock.filename.buf);
356357
if (update_main_cache_tree(WRITE_TREE_SILENT) == 0) {
357358
if (reopen_lock_file(&index_lock) < 0)
358359
die(_("unable to write index file"));
@@ -362,7 +363,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
362363
warning(_("Failed to update main cache tree"));
363364

364365
commit_style = COMMIT_NORMAL;
365-
return index_lock.filename;
366+
return index_lock.filename.buf;
366367
}
367368

368369
/*
@@ -385,7 +386,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
385386
if (write_locked_index(&the_index, &index_lock, CLOSE_LOCK))
386387
die(_("unable to write new_index file"));
387388
commit_style = COMMIT_NORMAL;
388-
return index_lock.filename;
389+
return index_lock.filename.buf;
389390
}
390391

391392
/*
@@ -472,9 +473,9 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
472473
die(_("unable to write temporary index file"));
473474

474475
discard_cache();
475-
read_cache_from(false_lock.filename);
476+
read_cache_from(false_lock.filename.buf);
476477

477-
return false_lock.filename;
478+
return false_lock.filename.buf;
478479
}
479480

480481
static int run_status(FILE *fp, const char *index_file, const char *prefix, int nowarn,

builtin/describe.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "cache.h"
2+
#include "lockfile.h"
23
#include "commit.h"
34
#include "tag.h"
45
#include "refs.h"

builtin/diff.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Copyright (c) 2006 Junio C Hamano
55
*/
66
#include "cache.h"
7+
#include "lockfile.h"
78
#include "color.h"
89
#include "commit.h"
910
#include "blob.h"

builtin/gc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*/
1212

1313
#include "builtin.h"
14-
#include "cache.h"
14+
#include "lockfile.h"
1515
#include "parse-options.h"
1616
#include "run-command.h"
1717
#include "sigchain.h"

0 commit comments

Comments
 (0)