@@ -38,6 +38,7 @@ typedef struct conn_s {
3838 struct conn_s * next ;
3939} conn_t ;
4040
41+ static int exit_flag = 0 ;
4142static DWORD upsd_pid = 0 ;
4243static DWORD upsmon_pid = 0 ;
4344static DWORD upsdrvctl_pid = 0 ;
@@ -581,6 +582,54 @@ static void ReportSvcStatus(
581582 SetServiceStatus (SvcStatusHandle , & SvcStatus );
582583}
583584
585+ /* For `nut.exe -N` runs
586+ * https://learn.microsoft.com/en-us/windows/console/registering-a-control-handler-function
587+ */
588+ static BOOL WINAPI ConsoleCtrlHandler (DWORD Ctrl )
589+ {
590+ switch (Ctrl )
591+ {
592+ case CTRL_C_EVENT :
593+ print_event (LOG_INFO , "Ctrl+C received on console" );
594+ exit_flag = 1 ; /* Break SvcMain() infinite loop */
595+ if (upsmon_pid ) {
596+ print_event (LOG_INFO , "Stopping upsmon" );
597+ stop_upsmon ();
598+ }
599+ if (upsd_pid ) {
600+ print_event (LOG_INFO , "Stopping upsd" );
601+ stop_upsd ();
602+ }
603+ if (upsdrvctl_pid ) {
604+ print_event (LOG_INFO , "Stopping drivers" );
605+ stop_drivers ();
606+ }
607+ exit_flag = 2 ; /* Allow to finish SvcMain() infinite loop and proceed to exit() */
608+ /* confirm that the user wants to exit */
609+ return TRUE;
610+
611+ case CTRL_CLOSE_EVENT :
612+ print_event (LOG_INFO , "Close event received on console, currently ignored" );
613+ return FALSE;
614+
615+ case CTRL_BREAK_EVENT :
616+ print_event (LOG_INFO , "Ctrl+Break event received on console, currently ignored" );
617+ return FALSE;
618+
619+ /* TOTHINK: Do we in fact want these two handled specially? */
620+ case CTRL_LOGOFF_EVENT :
621+ print_event (LOG_INFO , "Logoff event received on console, currently ignored" );
622+ return FALSE;
623+
624+ case CTRL_SHUTDOWN_EVENT :
625+ print_event (LOG_INFO , "Shutdown event received on console, currently ignored" );
626+ return FALSE;
627+
628+ default :
629+ return FALSE;
630+ }
631+ }
632+
584633static void WINAPI SvcCtrlHandler (DWORD Ctrl )
585634{
586635 switch (Ctrl )
@@ -659,7 +708,7 @@ static void close_all(void)
659708static void WINAPI SvcMain (DWORD argc , LPTSTR * argv )
660709{
661710 DWORD ret ;
662- HANDLE handles [MAXIMUM_WAIT_OBJECTS ]; /* 64 per current WinAPI sheaders */
711+ HANDLE handles [MAXIMUM_WAIT_OBJECTS ]; /* 64 per current WinAPI headers */
663712 size_t maxhandle = 0 ;
664713 pipe_conn_t * conn ;
665714 DWORD priority ;
@@ -697,7 +746,7 @@ static void WINAPI SvcMain(DWORD argc, LPTSTR *argv)
697746 SvcReady ();
698747 }
699748
700- while (1 ) {
749+ while (! exit_flag ) {
701750 maxhandle = 0 ;
702751 memset (& handles , 0 , sizeof (handles ));
703752
@@ -766,6 +815,10 @@ static void WINAPI SvcMain(DWORD argc, LPTSTR *argv)
766815 }
767816 }
768817
818+ /* Do not check on daemons nor revive them in vain if we are exiting */
819+ if (exit_flag )
820+ break ;
821+
769822 /* Check on each daemon: Was it supposed to run? Does it still? */
770823 if (upsdrvctl_pid ) {
771824 DWORD status = 0 ;
@@ -785,6 +838,10 @@ static void WINAPI SvcMain(DWORD argc, LPTSTR *argv)
785838 }
786839 }
787840
841+ /* Do not check on daemons nor revive them in vain if we are exiting */
842+ if (exit_flag )
843+ break ;
844+
788845 if (upsd_pid ) {
789846 DWORD status = 0 ;
790847 BOOL res = FALSE;
@@ -803,6 +860,10 @@ static void WINAPI SvcMain(DWORD argc, LPTSTR *argv)
803860 }
804861 }
805862
863+ /* Do not check on daemons nor revive them in vain if we are exiting */
864+ if (exit_flag )
865+ break ;
866+
806867 if (upsmon_pid ) {
807868 DWORD status = 0 ;
808869 BOOL res = FALSE;
@@ -821,6 +882,10 @@ static void WINAPI SvcMain(DWORD argc, LPTSTR *argv)
821882 }
822883 }
823884 }
885+
886+ while (exit_flag < 2 ) {
887+ Sleep (1000 );
888+ }
824889}
825890
826891static void help (const char * arg_progname )
@@ -1020,6 +1085,10 @@ int main(int argc, char **argv)
10201085 }
10211086 }
10221087 else {
1088+ if (!SetConsoleCtrlHandler (ConsoleCtrlHandler , TRUE)) {
1089+ upslog_with_errno (LOG_ERR , "SetConsoleCtrlHandler failed, may ignore Ctrl+C" );
1090+ }
1091+
10231092 SvcMain (argc , argv );
10241093 }
10251094
0 commit comments