Skip to content

Commit d6cf61b

Browse files
drafnelgitster
authored andcommitted
close_lock_file(): new function in the lockfile API
The lockfile API is a handy way to obtain a file that is cleaned up if you die(). But sometimes you would need this sequence to work: 1. hold_lock_file_for_update() to get a file descriptor for writing; 2. write the contents out, without being able to decide if the results should be committed or rolled back; 3. do something else that makes the decision --- and this "something else" needs the lockfile not to have an open file descriptor for writing (e.g. Windows do not want a open file to be renamed); 4. call commit_lock_file() or rollback_lock_file() as appropriately. This adds close_lock_file() you can call between step 2 and 3 in the above sequence. Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 0c0478c commit d6cf61b

File tree

3 files changed

+35
-12
lines changed

3 files changed

+35
-12
lines changed

Documentation/technical/api-lockfile.txt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,21 @@ commit_lock_file::
3737
Take a pointer to the `struct lock_file` initialized
3838
with an earlier call to `hold_lock_file_for_update()`,
3939
close the file descriptor and rename the lockfile to its
40-
final destination.
40+
final destination. Returns 0 upon success, a negative
41+
value on failure to close(2) or rename(2).
4142

4243
rollback_lock_file::
4344

4445
Take a pointer to the `struct lock_file` initialized
4546
with an earlier call to `hold_lock_file_for_update()`,
4647
close the file descriptor and remove the lockfile.
4748

49+
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+
4855
Because the structure is used in an `atexit(3)` handler, its
4956
storage has to stay throughout the life of the program. It
5057
cannot be an auto variable allocated on the stack.
@@ -54,8 +61,10 @@ done writing to the file descriptor. If you do not call either
5461
and simply `exit(3)` from the program, an `atexit(3)` handler
5562
will close and remove the lockfile.
5663

57-
You should not close the file descriptor you obtained from
58-
`hold_lock_file_for_update` function yourself. The `struct
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
5968
lock_file` structure still remembers that the file descriptor
6069
needs to be closed, and a later call to `commit_lock_file()` or
6170
`rollback_lock_file()` will result in duplicate calls to

cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ extern int commit_lock_file(struct lock_file *);
308308
extern int hold_locked_index(struct lock_file *, int);
309309
extern int commit_locked_index(struct lock_file *);
310310
extern void set_alternate_index_output(const char *);
311-
311+
extern int close_lock_file(struct lock_file *);
312312
extern void rollback_lock_file(struct lock_file *);
313313
extern int delete_ref(const char *, const unsigned char *sha1);
314314

lockfile.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ static void remove_lock_file(void)
1313
while (lock_file_list) {
1414
if (lock_file_list->owner == me &&
1515
lock_file_list->filename[0]) {
16-
close(lock_file_list->fd);
16+
if (lock_file_list->fd >= 0)
17+
close(lock_file_list->fd);
1718
unlink(lock_file_list->filename);
1819
}
1920
lock_file_list = lock_file_list->next;
@@ -159,17 +160,26 @@ int hold_lock_file_for_update(struct lock_file *lk, const char *path, int die_on
159160
return fd;
160161
}
161162

163+
int close_lock_file(struct lock_file *lk)
164+
{
165+
int fd = lk->fd;
166+
lk->fd = -1;
167+
return close(fd);
168+
}
169+
162170
int commit_lock_file(struct lock_file *lk)
163171
{
164172
char result_file[PATH_MAX];
165-
int i;
166-
close(lk->fd);
173+
size_t i;
174+
if (lk->fd >= 0 && close_lock_file(lk))
175+
return -1;
167176
strcpy(result_file, lk->filename);
168177
i = strlen(result_file) - 5; /* .lock */
169178
result_file[i] = 0;
170-
i = rename(lk->filename, result_file);
179+
if (rename(lk->filename, result_file))
180+
return -1;
171181
lk->filename[0] = 0;
172-
return i;
182+
return 0;
173183
}
174184

175185
int hold_locked_index(struct lock_file *lk, int die_on_error)
@@ -185,9 +195,12 @@ void set_alternate_index_output(const char *name)
185195
int commit_locked_index(struct lock_file *lk)
186196
{
187197
if (alternate_index_output) {
188-
int result = rename(lk->filename, alternate_index_output);
198+
if (lk->fd >= 0 && close_lock_file(lk))
199+
return -1;
200+
if (rename(lk->filename, alternate_index_output))
201+
return -1;
189202
lk->filename[0] = 0;
190-
return result;
203+
return 0;
191204
}
192205
else
193206
return commit_lock_file(lk);
@@ -196,7 +209,8 @@ int commit_locked_index(struct lock_file *lk)
196209
void rollback_lock_file(struct lock_file *lk)
197210
{
198211
if (lk->filename[0]) {
199-
close(lk->fd);
212+
if (lk->fd >= 0)
213+
close(lk->fd);
200214
unlink(lk->filename);
201215
}
202216
lk->filename[0] = 0;

0 commit comments

Comments
 (0)