@@ -1160,6 +1160,69 @@ void test_proc_smooth_recovery6()
1160
1160
sset.remove_service (&p);
1161
1161
}
1162
1162
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
+
1163
1226
// simulate the launcher process forking a daemon process, and supply the process ID of that
1164
1227
// daemon process in a pid file.
1165
1228
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)
2374
2437
RUN_TEST (test_proc_smooth_recovery4, " " );
2375
2438
RUN_TEST (test_proc_smooth_recovery5, " " );
2376
2439
RUN_TEST (test_proc_smooth_recovery6, " " );
2440
+ RUN_TEST (test_proc_smooth_recovery6a, " " );
2377
2441
RUN_TEST (test_bgproc_start, " " );
2378
2442
RUN_TEST (test_bgproc_start_fail, " " );
2379
2443
RUN_TEST (test_bgproc_start_fail_pid, " " );
0 commit comments