[PATCH] merge-ll: Cleanup merge driver temporaries after interrupt
- From
- Michal Koutný <mkoutny@suse.com>
- Date
- Sep 10, 2026, 15:06 UTC
- Message-ID
- <20260910150608.1867930-1-mkoutny@suse.com>
When there's a long(er) running merge driver helper, the user may just decide to terminate it with Ctrl+C. That sends a signal to the driver prog and to the whole process group as well, including the git merge command proper. Hence the cleanup code would not run and .merge_file_* files are left behind.
Transfer the idiom [1] from editor.c where the (process group) signal delivery is approximated from the return code of the child process and do the cleanup before going for good.
[1] Note: when the helper SIGINTs alone, it'd tear down the git-merge too.
Reported-by: Jean Delvare <jdelvare@suse.de> Signed-off-by: Michal Koutný <mkoutny@suse.com> --- merge-ll.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/merge-ll.c b/merge-ll.c index ef5287dee8..bee30fb5dd 100644 --- a/merge-ll.c +++ b/merge-ll.c @@ -17,6 +17,7 @@ #include "quote.h" #include "strbuf.h" #include "gettext.h" +#include "sigchain.h" struct ll_merge_driver; @@ -201,7 +202,7 @@ static enum ll_merge_result ll_ext_merge(const struct ll_merge_driver *fn, struct strbuf cmd = STRBUF_INIT; const char *format = fn->cmdline; struct child_process child = CHILD_PROCESS_INIT; - int status, fd, i; + int status, fd, i, sig; struct stat st; enum ll_merge_result ret; assert(opts); @@ -240,7 +241,13 @@ static enum ll_merge_result ll_ext_merge(const struct ll_merge_driver *fn, child.use_shell = 1; strvec_push(&child.args, cmd.buf); - status = run_command(&child); + status = -1; + if (start_command(&child) < 0) + goto bad; + sigchain_push(SIGINT, SIG_IGN); + sigchain_push(SIGQUIT, SIG_IGN); + status = finish_command(&child); + fd = open(temp[1], O_RDONLY); if (fd < 0) goto bad; @@ -262,9 +269,15 @@ static enum ll_merge_result ll_ext_merge(const struct ll_merge_driver *fn, ret = LL_MERGE_OK; else if (status <= 128) ret = LL_MERGE_CONFLICT; - else + else { /* died due to a signal: WTERMSIG(status) + 128 */ + sig = status - 128; + sigchain_pop(SIGINT); + sigchain_pop(SIGQUIT); + if (sig == SIGINT || sig == SIGQUIT) + raise(sig); ret = LL_MERGE_ERROR; + } return ret; }
-- 2.55.0