@@ -54,6 +54,7 @@ typedef struct {
5454 pid_t pid ;
5555#else /* WIN32 */
5656 int pid ; /* for WIN32 used just as a flag that this UPS was started by this tool in this run */
57+ PROCESS_INFORMATION ProcessInformation ;
5758#endif /* WIN32 */
5859 void * next ;
5960} ups_t ;
@@ -807,12 +808,24 @@ static void debugcmdline(int level, const char *msg, char *const argv[])
807808}
808809
809810#ifndef WIN32
810- static int forkexec_parent_analyze (pid_t waitret , int wstat , int * puexectimeout )
811+ static int forkexec_parent_analyze (pid_t waitret , int wstat , const ups_t * ups )
812+ #else
813+ static int forkexec_parent_analyze (DWORD res , const ups_t * ups )
814+ #endif
811815{
816+ /* work around const for this one... */
817+ #ifdef WIN32
818+ int * pupid = (int * )& (ups -> pid );
819+ #endif
820+ int * puexectimeout = (int * )& (ups -> exceeded_timeout );
821+
822+ * puexectimeout = 0 ;
823+
824+ #ifndef WIN32
812825 if (waitret == -1 ) {
813826 upslogx (LOG_WARNING , "Startup timer elapsed, continuing..." );
814827 exec_timeout ++ ;
815- if ( puexectimeout ) * puexectimeout = 1 ;
828+ * puexectimeout = 1 ;
816829 return 0 ;
817830 }
818831
@@ -838,10 +851,28 @@ static int forkexec_parent_analyze(pid_t waitret, int wstat, int *puexectimeout)
838851 return -3 ;
839852 }
840853
841- if (puexectimeout ) * puexectimeout = 0 ;
854+ #else /* WIN32 */
855+
856+ if (res == WAIT_OBJECT_0 ) {
857+ /* all ok, no-op */
858+ } else
859+ if (res == WAIT_TIMEOUT ) {
860+ upslogx (LOG_WARNING , "Startup timer elapsed, continuing..." );
861+ * pupid = 0 ; /* For WIN32, just a flag (not "-1" has a meaning) */
862+ * puexectimeout = 1 ;
863+ return 0 ;
864+ } else {
865+ DWORD exit_code = 0 ;
866+ GetExitCodeProcess ( ups -> ProcessInformation .hProcess , & exit_code );
867+ upslogx (LOG_WARNING , "Driver failed to start (exit status=%d)" , exit_code );
868+ exec_error ++ ;
869+ return -2 ;
870+ }
871+ #endif /* WIN32 */
872+
873+ upsdebugx (3 , "%s: startup seems successful" , __func__ );
842874 return 1 ;
843875}
844- #endif /* WIN32 */
845876
846877static void forkexec (char * const argv [], const ups_t * ups )
847878{
@@ -943,7 +974,7 @@ static void forkexec(char *const argv[], const ups_t *ups)
943974 alarm (0 );
944975
945976 /* Bump timeout or error counts if appropriate */
946- forkexec_parent_analyze (waitret , wstat , puexectimeout );
977+ forkexec_parent_analyze (waitret , wstat , ups );
947978
948979 return ;
949980 } /* end of pid != 0 (fork parent) part */
@@ -970,13 +1001,14 @@ static void forkexec(char *const argv[], const ups_t *ups)
9701001#else /* WIN32 */
9711002 BOOL ret ;
9721003 DWORD res ;
973- DWORD exit_code = 0 ;
9741004 char commandline [LARGEBUF ];
9751005 STARTUPINFO StartupInfo ;
976- PROCESS_INFORMATION ProcessInformation ;
1006+ /* work around const for this one... */
1007+ PROCESS_INFORMATION * pProcessInformation = (PROCESS_INFORMATION * )& (ups -> ProcessInformation );
9771008 int i = 1 , waited = 0 ;
9781009
9791010 memset (& StartupInfo , 0 , sizeof (STARTUPINFO ));
1011+ memset (pProcessInformation , 0 , sizeof (PROCESS_INFORMATION ));
9801012
9811013 /* the command line is made of the driver name followed by args */
9821014 if (strstr (argv [0 ], ups -> driver )) {
@@ -1014,16 +1046,18 @@ static void forkexec(char *const argv[], const ups_t *ups)
10141046 NULL ,
10151047 NULL ,
10161048 & StartupInfo ,
1017- & ProcessInformation
1049+ pProcessInformation
10181050 );
10191051
1020- if (ret == 0 ) {
1052+ if (! ret ) {
10211053 fatal_with_errno (EXIT_FAILURE , "execv" );
10221054 }
10231055
10241056 /* Wait a bit then look at driver process.
1025- * Unlike under Linux, Windows spawn drivers directly. If the driver is alive, all is OK.
1026- * An optimization can probably be implemented to prevent waiting so much time when all is OK.
1057+ * Unlike under Linux, Windows spawn drivers directly.
1058+ * If the driver is alive, all is OK.
1059+ * An optimization can probably be implemented
1060+ * to prevent waiting so much time when all is OK.
10271061 */
10281062
10291063 /* Use the local maxstartdelay, if available */
@@ -1033,7 +1067,7 @@ static void forkexec(char *const argv[], const ups_t *ups)
10331067 "to check that driver survived this long "
10341068 "(per device configuration section)" ,
10351069 __func__ , (unsigned int )ups -> maxstartdelay );
1036- res = WaitForSingleObject (ProcessInformation . hProcess ,
1070+ res = WaitForSingleObject (pProcessInformation -> hProcess ,
10371071 ((unsigned int )ups -> maxstartdelay ) * 1000 );
10381072 waited = 1 ;
10391073 }
@@ -1043,7 +1077,7 @@ static void forkexec(char *const argv[], const ups_t *ups)
10431077 "to check that driver survived this long "
10441078 "(per global configuration section)" ,
10451079 __func__ , (unsigned int )maxstartdelay );
1046- res = WaitForSingleObject (ProcessInformation . hProcess ,
1080+ res = WaitForSingleObject (pProcessInformation -> hProcess ,
10471081 ((unsigned int )maxstartdelay ) * 1000 );
10481082 waited = 1 ;
10491083 }
@@ -1054,22 +1088,11 @@ static void forkexec(char *const argv[], const ups_t *ups)
10541088 "to check that driver survived this long "
10551089 "(not required by global nor by device "
10561090 "configuration sections)" , __func__ );
1057- res = WaitForSingleObject (ProcessInformation . hProcess ,
1091+ res = WaitForSingleObject (pProcessInformation -> hProcess ,
10581092 0 );
10591093 }
10601094
1061- if (res != WAIT_TIMEOUT ) {
1062- GetExitCodeProcess ( ProcessInformation .hProcess , & exit_code );
1063- upslogx (LOG_WARNING , "Driver failed to start (exit status=%d)" , ret );
1064- exec_error ++ ;
1065- return ;
1066- } else {
1067- /* work around const for this one... */
1068- int * pupid = (int * )& (ups -> pid );
1069- int * puexectimeout = (int * )& (ups -> exceeded_timeout );
1070- * pupid = 0 ; /* For WIN32, just a flag (not "-1" has a meaning) */
1071- * puexectimeout = 1 ;
1072- }
1095+ forkexec_parent_analyze (res , ups );
10731096
10741097 return ;
10751098#endif /* WIN32 */
@@ -1447,22 +1470,23 @@ static void start_driver(const ups_t *ups)
14471470 /* otherwise, retry if still needed */
14481471 if (drv_maxretry > 0 )
14491472 if (drv_retrydelay >= 0 ) {
1450- #ifndef WIN32
1451- int * puexectimeout = (int * )& (ups -> exceeded_timeout );
1452- #endif
1453-
14541473 upsdebugx (3 , "%s: retrying after %u seconds" ,
14551474 __func__ , (unsigned int )drv_retrydelay );
14561475 sleep ((unsigned int )drv_retrydelay );
14571476
1477+ if (upscount > 1 && ups -> exceeded_timeout ) {
1478+ /* Final checks, similar to those in forkexec() */
14581479#ifndef WIN32
1459- if (upscount > 1 && * puexectimeout ) {
14601480 int wstat ;
14611481 pid_t waitret ;
14621482
1463- /* Final checks, similar to those in forkexec() */
14641483 waitret = waitpid (ups -> pid , & wstat , WNOHANG );
1465- if (forkexec_parent_analyze (waitret , wstat , puexectimeout ) > 0 ) {
1484+ if (forkexec_parent_analyze (waitret , wstat , ups ) > 0 )
1485+ #else
1486+ DWORD res = WaitForSingleObject (ups -> ProcessInformation -> hProcess , 0 );
1487+ if (forkexec_parent_analyze (res , ups ))
1488+ #endif
1489+ {
14661490 upslogx (LOG_INFO , "%s: driver %s [%s] completed startup "
14671491 "while we were sleeping to retry" , __func__ ,
14681492 ups -> driver , ups -> upsname );
@@ -1471,7 +1495,6 @@ static void start_driver(const ups_t *ups)
14711495 exec_timeout = initial_exec_timeout ;
14721496 }
14731497 }
1474- #endif
14751498
14761499 }
14771500 }
0 commit comments