From: Michal Koutný Date: Thu, 10 Sep 2026 15:06:07 GMT Subject: [PATCH] merge-ll: Cleanup merge driver temporaries after interrupt 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 Signed-off-by: Michal Koutný --- 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