@@ -34,8 +34,10 @@ class StartCommand extends Command
3434 /**
3535 * Execute the console command.
3636 */
37- public function handle ()
37+ public function handle (): int
3838 {
39+ $ this ->listenForSignals ();
40+
3941 $ keepUp = $ this ->option ('reset ' ) ? false : true ;
4042 $ trigger = Trigger::replication ($ this ->option ('replication ' ));
4143
@@ -91,5 +93,34 @@ public function handle()
9193
9294 goto start;
9395 }
96+
97+ return Command::SUCCESS ;
98+ }
99+
100+ /**
101+ * Register SIGTERM/SIGINT handlers for immediate shutdown.
102+ *
103+ * The start() method blocks inside MySQLReplicationFactory::run() reading
104+ * from a socket. Setting a flag is insufficient because the blocking read
105+ * never returns to check it. We must exit directly from the signal handler,
106+ * matching the pattern used by the library's own Terminate subscriber.
107+ */
108+ protected function listenForSignals (): void
109+ {
110+ if (! function_exists ('pcntl_async_signals ' ) || ! function_exists ('pcntl_signal ' )) {
111+ return ;
112+ }
113+
114+ pcntl_async_signals (true );
115+
116+ $ handler = function (int $ signal ) {
117+ $ name = $ signal === SIGTERM ? 'SIGTERM ' : 'SIGINT ' ;
118+ $ this ->info ("Received {$ name }, shutting down... " );
119+
120+ exit (0 );
121+ };
122+
123+ pcntl_signal (SIGTERM , $ handler );
124+ pcntl_signal (SIGINT , $ handler );
94125 }
95126}
0 commit comments