6
#include "abspath.h"
7
#include "gettext.h"
8
#include "lockfile.h"
9
+#include "parse.h"
10
+#include "strbuf.h"
11
+#include "wrapper.h"
12
13
/*
14
* path = absolute or relative path name
74
strbuf_reset(&link);
75
}
76
77
+/*
78
+ * Lock PID file functions - write PID to a foo~pid.lock file alongside
79
+ * the lock file for debugging stale locks. The PID file is registered
80
+ * as a tempfile so it gets cleaned up by signal/atexit handlers.
81
+ *
82
+ * Naming: For "foo.lock", the PID file is "foo~pid.lock". The tilde is
83
+ * forbidden in refnames and allowed in Windows filenames, guaranteeing
84
+ * no collision with the refs namespace.
85
+ */
86
+
87
+/* Global config variable, initialized from core.lockfilePid */
88
+int lockfile_pid_enabled;
89
+
90
+/*
91
+ * Path generation helpers.
92
+ * Given base path "foo", generate:
93
+ * - lock path: "foo.lock"
94
+ * - pid path: "foo-pid.lock"
95
+ */
96
+static void get_lock_path(struct strbuf *out, const char *path)
97
+{
98
+ strbuf_addstr(out, path);
99
+ strbuf_addstr(out, LOCK_SUFFIX);
100
+}
101
+
102
+static void get_pid_path(struct strbuf *out, const char *path)
103
+{
104
+ strbuf_addstr(out, path);
105
+ strbuf_addstr(out, LOCK_PID_INFIX);
106
+ strbuf_addstr(out, LOCK_SUFFIX);
107
+}
108
+
109
+static struct tempfile *create_lock_pid_file(const char *pid_path, int mode)
110
+{
111
+ struct strbuf content = STRBUF_INIT;
112
+ struct tempfile *pid_tempfile = NULL;
113
+ int fd;
114
+
115
+ if (!lockfile_pid_enabled)
116
+ goto out;
117
+
118
+ fd = open(pid_path, O_WRONLY | O_CREAT | O_EXCL, mode);
119
+ if (fd < 0)
120
+ goto out;
121
+
122
+ strbuf_addf(&content, "pid %" PRIuMAX "\n", (uintmax_t)getpid());
123
+ if (write_in_full(fd, content.buf, content.len) < 0) {
124
+ warning_errno(_("could not write lock pid file '%s'"), pid_path);
125
+ close(fd);
126
+ unlink(pid_path);
127
+ goto out;
128
+ }
129
+
130
+ close(fd);
131
+ pid_tempfile = register_tempfile(pid_path);
132
+
133
+out:
134
+ strbuf_release(&content);
135
+ return pid_tempfile;
136
+}
137
+
138
+static int read_lock_pid(const char *pid_path, uintmax_t *pid_out)
139
+{
140
+ struct strbuf content = STRBUF_INIT;
141
+ const char *val;
142
+ int ret = -1;
143
+
144
+ if (strbuf_read_file(&content, pid_path, LOCK_PID_MAXLEN) <= 0)
145
+ goto out;
146
+
147
+ strbuf_rtrim(&content);
148
+
149
+ if (skip_prefix(content.buf, "pid ", &val)) {
150
+ char *endptr;
151
+ *pid_out = strtoumax(val, &endptr, 10);
152
+ if (*pid_out > 0 && !*endptr)
153
+ ret = 0;
154
+ }
155
+
156
+ if (ret)
157
+ warning(_("malformed lock pid file '%s'"), pid_path);
158
+
159
+out:
160
+ strbuf_release(&content);
161
+ return ret;
162
+}
163
+
164
/* Make sure errno contains a meaningful value on error */
165
static int lock_file(struct lock_file *lk, const char *path, int flags,
166
int mode)
167
{
78
- struct strbuf filename = STRBUF_INIT;
168
+ struct strbuf base_path = STRBUF_INIT;
169
+ struct strbuf lock_path = STRBUF_INIT;
170
+ struct strbuf pid_path = STRBUF_INIT;
171
80
- strbuf_addstr(&filename, path);
172
+ strbuf_addstr(&base_path, path);
173
if (!(flags & LOCK_NO_DEREF))
82
- resolve_symlink(&filename);
174
+ resolve_symlink(&base_path);
175
+
176
+ get_lock_path(&lock_path, base_path.buf);
177
+ get_pid_path(&pid_path, base_path.buf);
178
+
179
+ lk->tempfile = create_tempfile_mode(lock_path.buf, mode);
180
+ if (lk->tempfile)
181
+ lk->pid_tempfile = create_lock_pid_file(pid_path.buf, mode);
182
84
- strbuf_addstr(&filename, LOCK_SUFFIX);
85
- lk->tempfile = create_tempfile_mode(filename.buf, mode);
86
- strbuf_release(&filename);
183
+ strbuf_release(&base_path);
184
+ strbuf_release(&lock_path);
185
+ strbuf_release(&pid_path);
186
return lk->tempfile ? lk->tempfile->fd : -1;
187
}
188
250
void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
251
{
252
if (err == EEXIST) {
154
- strbuf_addf(buf, _("Unable to create '%s.lock': %s.\n\n"
155
- "Another git process seems to be running in this repository, e.g.\n"
156
- "an editor opened by 'git commit'. Please make sure all processes\n"
157
- "are terminated then try again. If it still fails, a git process\n"
158
- "may have crashed in this repository earlier:\n"
159
- "remove the file manually to continue."),
160
- absolute_path(path), strerror(err));
161
- } else
253
+ const char *abs_path = absolute_path(path);
254
+ struct strbuf lock_path = STRBUF_INIT;
255
+ struct strbuf pid_path = STRBUF_INIT;
256
+ uintmax_t pid;
257
+ int pid_status = 0; /* 0 = unknown, 1 = running, -1 = stale */
258
+
259
+ get_lock_path(&lock_path, abs_path);
260
+ get_pid_path(&pid_path, abs_path);
261
+
262
+ strbuf_addf(buf, _("Unable to create '%s': %s.\n\n"),
263
+ lock_path.buf, strerror(err));
264
+
265
+ /*
266
+ * Try to read PID file unconditionally - it may exist if
267
+ * core.lockfilePid was enabled.
268
+ */
269
+ if (!read_lock_pid(pid_path.buf, &pid)) {
270
+ if (kill((pid_t)pid, 0) == 0 || errno == EPERM)
271
+ pid_status = 1; /* running (or no permission to signal) */
272
+ else if (errno == ESRCH)
273
+ pid_status = -1; /* no such process - stale lock */
274
+ }
275
+
276
+ if (pid_status == 1)
277
+ strbuf_addf(buf, _("Lock may be held by process %" PRIuMAX "; "
278
+ "if no git process is running, the lock file "
279
+ "may be stale (PIDs can be reused)"),
280
+ pid);
281
+ else if (pid_status == -1)
282
+ strbuf_addf(buf, _("Lock was held by process %" PRIuMAX ", "
283
+ "which is no longer running; the lock file "
284
+ "appears to be stale"),
285
+ pid);
286
+ else
287
+ strbuf_addstr(buf, _("Another git process seems to be running in this repository, "
288
+ "or the lock file may be stale"));
289
+
290
+ strbuf_release(&lock_path);
291
+ strbuf_release(&pid_path);
292
+ } else {
293
strbuf_addf(buf, _("Unable to create '%s.lock': %s"),
294
absolute_path(path), strerror(err));
295
+ }
296
}
297
298
NORETURN void unable_to_lock_die(const char *path, int err)
339
{
340
char *result_path = get_locked_file_path(lk);
341
342
+ delete_tempfile(&lk->pid_tempfile);
343
+
344
if (commit_lock_file_to(lk, result_path)) {
345
int save_errno = errno;
346
free(result_path);
350
free(result_path);
351
return 0;
352
}
353
+
354
+int rollback_lock_file(struct lock_file *lk)
355
+{
356
+ delete_tempfile(&lk->pid_tempfile);
357
+ return delete_tempfile(&lk->tempfile);
358
+}