Skip to content

Commit 1738bdc

Browse files
committed
handle terminal resize while running external program
1 parent 999dfc6 commit 1738bdc

File tree

3 files changed

+43
-5
lines changed

3 files changed

+43
-5
lines changed

src/nmail.1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
2-
.TH NMAIL "1" "February 2026" "nmail 5.11.4" "User Commands"
2+
.TH NMAIL "1" "March 2026" "nmail 5.12.1" "User Commands"
33
.SH NAME
44
nmail \- ncurses mail
55
.SH SYNOPSIS

src/util.cpp

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "util.h"
99

1010
#include <algorithm>
11+
#include <cerrno>
1112
#include <csignal>
1213
#include <cstring>
1314
#include <fstream>
@@ -2336,15 +2337,52 @@ int Util::System(const std::string& p_Cmd)
23362337
static const std::string shPath = "/bin/sh";
23372338
#endif
23382339

2340+
// Block SIGCHLD and ignore SIGINT/SIGQUIT in parent per POSIX system() spec
2341+
struct sigaction saIgnore;
2342+
struct sigaction saOrigInt;
2343+
struct sigaction saOrigQuit;
2344+
saIgnore.sa_handler = SIG_IGN;
2345+
sigemptyset(&saIgnore.sa_mask);
2346+
saIgnore.sa_flags = 0;
2347+
sigaction(SIGINT, &saIgnore, &saOrigInt);
2348+
sigaction(SIGQUIT, &saIgnore, &saOrigQuit);
2349+
2350+
sigset_t blockChld;
2351+
sigset_t origMask;
2352+
sigemptyset(&blockChld);
2353+
sigaddset(&blockChld, SIGCHLD);
2354+
sigprocmask(SIG_BLOCK, &blockChld, &origMask);
2355+
23392356
pid_t pid = fork();
23402357
if (pid == 0)
23412358
{
2359+
// Child: restore original signal dispositions and mask
2360+
sigaction(SIGINT, &saOrigInt, nullptr);
2361+
sigaction(SIGQUIT, &saOrigQuit, nullptr);
2362+
sigprocmask(SIG_SETMASK, &origMask, nullptr);
2363+
23422364
execl(shPath.c_str(), "sh", "-c", p_Cmd.c_str(), (char*)nullptr);
23432365
_exit(127);
23442366
}
23452367

2346-
if (pid < 0) return -1;
2368+
int status = -1;
2369+
if (pid > 0)
2370+
{
2371+
// Retry waitpid on EINTR (e.g. from SIGWINCH during terminal resize)
2372+
while (waitpid(pid, &status, 0) < 0)
2373+
{
2374+
if (errno != EINTR)
2375+
{
2376+
status = -1;
2377+
break;
2378+
}
2379+
}
2380+
}
2381+
2382+
// Restore original signal dispositions and mask
2383+
sigaction(SIGINT, &saOrigInt, nullptr);
2384+
sigaction(SIGQUIT, &saOrigQuit, nullptr);
2385+
sigprocmask(SIG_SETMASK, &origMask, nullptr);
23472386

2348-
int status = 0;
2349-
return (waitpid(pid, &status, 0) < 0) ? -1 : status;
2387+
return status;
23502388
}

src/version.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
#include "version.h"
99

10-
#define NMAIL_VERSION "5.11.4"
10+
#define NMAIL_VERSION "5.12.1"
1111

1212
std::string Version::GetBuildOs()
1313
{

0 commit comments

Comments
 (0)