Skip to content

Commit a53e721

Browse files
committed
trace: lock the trace file to avoid racy trace_write() calls
When multiple processes try to write to the same file, it is not guaranteed that everything works as expected: those writes can overlap, and in the worst case even lose messages. This happens in t/t5552-skipping-fetch-negotiator.sh, where we abuse the `GIT_TRACE` facility to write traces of two concurrent processes (`git fetch` and `git upload-pack`) to the same file, and then verify that the trace contains certain expected breadcrumbs. To remedy this, let's lock the file descriptors for exclusive writing, using the function we just introduced in the previous commit. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 8dda2d5 commit a53e721

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

trace.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,20 @@ static int prepare_trace_line(const char *file, int line,
114114

115115
static void trace_write(struct trace_key *key, const void *buf, unsigned len)
116116
{
117-
if (write_in_full(get_trace_fd(key), buf, len) < 0) {
117+
int fd = get_trace_fd(key), locked;
118+
119+
locked = !lock_or_unlock_fd_for_appending(fd, 1);
120+
if (!locked && errno != EBADF)
121+
warning("unable to lock file descriptor for %s: %s",
122+
key->key, strerror(errno));
123+
if (write_in_full(fd, buf, len) < 0) {
118124
warning("unable to write trace for %s: %s",
119125
key->key, strerror(errno));
120126
trace_disable(key);
121127
}
128+
if (locked && lock_or_unlock_fd_for_appending(fd, 0) < 0)
129+
warning("failed to remove lock on fd for %s: %s",
130+
key->key, strerror(errno));
122131
}
123132

124133
void trace_verbatim(struct trace_key *key, const void *buf, unsigned len)

0 commit comments

Comments
 (0)