Skip to content

Commit abdfc10

Browse files
committed
fix(cli): clean up desktop server process on shutdown
2 parents e8ac6f8 + 3fc942e commit abdfc10

3 files changed

Lines changed: 119 additions & 23 deletions

File tree

src/commands/DesktopCommand.cpp

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ namespace
6868

6969
bool startServer{false};
7070
bool waitForServer{true};
71-
std::chrono::milliseconds startupTimeout{5000};
71+
std::chrono::milliseconds startupTimeout{30000};
7272

7373
std::string serverCommand{};
7474
std::string serverWorkingDirectory{};
@@ -102,6 +102,53 @@ namespace
102102
return true;
103103
}
104104

105+
std::string shell_quote_env_value(const std::string &value)
106+
{
107+
std::string out;
108+
out.reserve(value.size() + 2);
109+
110+
out += "'";
111+
112+
for (char ch : value)
113+
{
114+
if (ch == '\'')
115+
{
116+
out += "'\\''";
117+
}
118+
else
119+
{
120+
out += ch;
121+
}
122+
}
123+
124+
out += "'";
125+
return out;
126+
}
127+
128+
std::string with_desktop_server_env(
129+
const DesktopOptions &options,
130+
const std::string &command)
131+
{
132+
if (command.empty())
133+
{
134+
return command;
135+
}
136+
137+
std::string out;
138+
139+
out += "SERVER_HOST=";
140+
out += shell_quote_env_value(options.host);
141+
out += " ";
142+
143+
out += "SERVER_PORT=";
144+
out += std::to_string(options.port);
145+
out += " ";
146+
147+
out += command;
148+
149+
return out;
150+
}
151+
105152
bool parse_positive_int(const std::string &value, int &out)
106153
{
107154
if (value.empty())
@@ -651,7 +698,8 @@ namespace
651698

652699
if (!options.serverCommand.empty())
653700
{
654-
config.set_server_command(options.serverCommand);
701+
config.set_server_command(
702+
with_desktop_server_env(options, options.serverCommand));
655703
}
656704

657705
if (!options.serverWorkingDirectory.empty())
@@ -684,8 +732,8 @@ namespace
684732

685733
vix::ui::AppShell shell(config);
686734

687-
info("Starting Vix desktop shell.");
688-
step(shell.target_url());
735+
info("Preparing Vix desktop shell.");
736+
step("target: " + shell.target_url());
689737

690738
vix::ui::Result<void> result = shell.start();
691739

@@ -786,7 +834,7 @@ namespace vix::commands
786834
<< " --working-directory <dir> Same as --cwd <dir>\n"
787835
<< " --wait Wait for the server to become reachable, default\n"
788836
<< " --no-wait Do not wait for server readiness\n"
789-
<< " --timeout-ms <ms> Server startup timeout. Default: 5000\n\n"
837+
<< " --timeout-ms <ms> Server startup timeout. Default: 30000\n\n"
790838

791839
<< "Metadata options:\n"
792840
<< " --app-id <id> Stable desktop application id\n"

src/commands/run/RunProcess.cpp

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,13 @@ namespace vix::commands::RunCommand::detail
191191

192192
namespace
193193
{
194-
static volatile sig_atomic_t g_sigint_requested = 0;
194+
static volatile sig_atomic_t g_signal_requested = 0;
195+
static volatile sig_atomic_t g_requested_signal = 0;
195196

196-
void on_sigint(int)
197+
void on_runtime_signal(int sig)
197198
{
198-
g_sigint_requested = 1;
199+
g_signal_requested = 1;
200+
g_requested_signal = sig;
199201
}
200202

201203
bool is_runtime_crash_noise_line(std::string_view line) noexcept
@@ -236,28 +238,58 @@ namespace vix::commands::RunCommand::detail
236238
return out;
237239
}
238240

239-
struct SigintGuard
241+
struct RuntimeSignalGuard
240242
{
241-
struct sigaction oldAction{};
242-
bool installed = false;
243+
struct sigaction oldInt{};
244+
struct sigaction oldTerm{};
245+
struct sigaction oldHup{};
243246

244-
SigintGuard()
247+
bool installedInt = false;
248+
bool installedTerm = false;
249+
bool installedHup = false;
250+
251+
RuntimeSignalGuard()
245252
{
246-
g_sigint_requested = 0;
253+
g_signal_requested = 0;
254+
g_requested_signal = 0;
247255

248256
struct sigaction sa{};
249-
sa.sa_handler = on_sigint;
257+
sa.sa_handler = on_runtime_signal;
250258
sigemptyset(&sa.sa_mask);
251259
sa.sa_flags = 0;
252260

253-
if (sigaction(SIGINT, &sa, &oldAction) == 0)
254-
installed = true;
261+
if (sigaction(SIGINT, &sa, &oldInt) == 0)
262+
{
263+
installedInt = true;
264+
}
265+
266+
if (sigaction(SIGTERM, &sa, &oldTerm) == 0)
267+
{
268+
installedTerm = true;
269+
}
270+
271+
if (sigaction(SIGHUP, &sa, &oldHup) == 0)
272+
{
273+
installedHup = true;
274+
}
255275
}
256276

257-
~SigintGuard()
277+
~RuntimeSignalGuard()
258278
{
259-
if (installed)
260-
sigaction(SIGINT, &oldAction, nullptr);
279+
if (installedInt)
280+
{
281+
sigaction(SIGINT, &oldInt, nullptr);
282+
}
283+
284+
if (installedTerm)
285+
{
286+
sigaction(SIGTERM, &oldTerm, nullptr);
287+
}
288+
289+
if (installedHup)
290+
{
291+
sigaction(SIGHUP, &oldHup, nullptr);
292+
}
261293
}
262294
};
263295

@@ -1297,7 +1329,7 @@ namespace vix::commands::RunCommand::detail
12971329
bool captureOnly,
12981330
vix::commands::replay::ReplayCapture *replayCapture)
12991331
{
1300-
SigintGuard sigGuard;
1332+
RuntimeSignalGuard signalGuard;
13011333
LiveRunResult result;
13021334

13031335
PtySession pty;
@@ -1465,10 +1497,15 @@ namespace vix::commands::RunCommand::detail
14651497

14661498
while (running)
14671499
{
1468-
if (!sentInt && g_sigint_requested)
1500+
if (!sentInt && g_signal_requested)
14691501
{
1470-
userInterrupted = true;
1471-
kill_group_or_pid(pid, SIGINT);
1502+
const int requestedSignal =
1503+
g_requested_signal > 0 ? static_cast<int>(g_requested_signal) : SIGTERM;
1504+
1505+
userInterrupted = requestedSignal == SIGINT;
1506+
1507+
kill_group_or_pid(pid, requestedSignal);
1508+
14721509
sentInt = true;
14731510
intTime = std::chrono::steady_clock::now();
14741511
}

src/commands/run/RunScript.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,12 +1088,23 @@ namespace vix::commands::RunCommand::detail
10881088
(rr.terminatedBySignal && rr.termSignal == SIGINT) ||
10891089
log_looks_like_interrupt(runtimeLog);
10901090

1091+
const bool stoppedByDesktopOrSupervisor =
1092+
opt.forceServerLike &&
1093+
((rr.terminatedBySignal &&
1094+
(rr.termSignal == SIGTERM || rr.termSignal == SIGHUP)) ||
1095+
runCode == 143 ||
1096+
runCode == 129);
1097+
10911098
if (interruptedBySigint)
10921099
{
10931100
hint("ℹ Program interrupted by user (SIGINT).");
10941101
return 0;
10951102
}
10961103

1104+
if (stoppedByDesktopOrSupervisor)
1105+
{
1106+
return 0;
1107+
}
10971108
const bool looksSanOrUb =
10981109
!runtimeLog.empty() && log_looks_like_sanitizer_or_ub(runtimeLog);
10991110

0 commit comments

Comments
 (0)