Skip to content

Commit 2d9f907

Browse files
committed
Correct handling of termination during smooth recovery with notification
When performing smooth recovery and waiting for readiness notification from the process, if the process terminates, this should be considered failure to start.
1 parent a2efdb7 commit 2d9f907

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

src/proc-service.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,11 @@ void process_service::handle_exit_status(bp_sys::exit_status exit_status) noexce
340340
if (waiting_stopstart_timer) {
341341
process_timer.stop_timer(event_loop);
342342
waiting_stopstart_timer = false;
343+
if (current_state == service_state_t::STARTED) {
344+
// Must have been in smooth recovery and waiting for readiness notification.
345+
// Treat this the same as if we were STARTING:
346+
current_state = service_state_t::STARTING;
347+
}
343348
}
344349

345350
#if USE_UTMPX

src/tests/proctests.cc

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,69 @@ void test_proc_smooth_recovery6()
11601160
sset.remove_service(&p);
11611161
}
11621162

1163+
// smooth recovery: termination while waiting for readiness notification
1164+
void test_proc_smooth_recovery6a()
1165+
{
1166+
using namespace std;
1167+
1168+
service_set sset;
1169+
1170+
ha_string command = "test-command";
1171+
list<pair<unsigned,unsigned>> command_offsets;
1172+
command_offsets.emplace_back(0, command.length());
1173+
std::list<prelim_dep> depends;
1174+
1175+
process_service p {&sset, "testproc", std::move(command), command_offsets, depends};
1176+
init_service_defaults(p);
1177+
p.set_smooth_recovery(true);
1178+
p.set_restart_delay(time_val {0, 1000});
1179+
p.set_start_timeout(time_val {1, 0});
1180+
p.set_notification_fd(3);
1181+
sset.add_service(&p);
1182+
1183+
p.start();
1184+
sset.process_queues();
1185+
1186+
base_process_service_test::exec_succeeded(&p);
1187+
sset.process_queues();
1188+
1189+
// readiness notification from process:
1190+
int nfd = base_process_service_test::get_notification_fd(&p);
1191+
char notifystr[] = "ok started\n";
1192+
std::vector<char> rnotifystr;
1193+
rnotifystr.insert(rnotifystr.end(), notifystr, notifystr + sizeof(notifystr));
1194+
bp_sys::supply_read_data(nfd, std::move(rnotifystr));
1195+
event_loop.regd_fd_watchers[nfd]->fd_event(event_loop, nfd, dasynq::IN_EVENTS);
1196+
assert(p.get_state() == service_state_t::STARTED);
1197+
assert(event_loop.active_timers.size() == 0);
1198+
1199+
pid_t first_instance = bp_sys::last_forked_pid;
1200+
1201+
assert(p.get_state() == service_state_t::STARTED);
1202+
1203+
base_process_service_test::handle_exit(&p, 0);
1204+
sset.process_queues();
1205+
1206+
event_loop.advance_time(time_val {0, 1000});
1207+
1208+
// new process should've been forked:
1209+
assert(first_instance != bp_sys::last_forked_pid);
1210+
assert(p.get_state() == service_state_t::STARTED);
1211+
assert(p.get_pid() == bp_sys::last_forked_pid);
1212+
1213+
base_process_service_test::exec_succeeded(&p);
1214+
sset.process_queues();
1215+
1216+
base_process_service_test::handle_exit(&p, 1);
1217+
sset.process_queues();
1218+
1219+
// The state should now be stopped:
1220+
assert(p.get_state() == service_state_t::STOPPED);
1221+
assert(event_loop.active_timers.size() == 0);
1222+
1223+
sset.remove_service(&p);
1224+
}
1225+
11631226
// simulate the launcher process forking a daemon process, and supply the process ID of that
11641227
// daemon process in a pid file.
11651228
static void supply_pid_contents(const char *pid_file, pid_t *daemon_instance_p = nullptr)
@@ -2374,6 +2437,7 @@ int main(int argc, char **argv)
23742437
RUN_TEST(test_proc_smooth_recovery4, " ");
23752438
RUN_TEST(test_proc_smooth_recovery5, " ");
23762439
RUN_TEST(test_proc_smooth_recovery6, " ");
2440+
RUN_TEST(test_proc_smooth_recovery6a, "");
23772441
RUN_TEST(test_bgproc_start, " ");
23782442
RUN_TEST(test_bgproc_start_fail, " ");
23792443
RUN_TEST(test_bgproc_start_fail_pid, " ");

0 commit comments

Comments
 (0)