Fossil SCM
Use a thread to implement the backoffice for Win32.
Commit
a9578f7870ced30545f987a324b1bfb87bd9e9e6a9af85adfc5ae63331e97e69
Parent
d5c41263af48fc1…
1 file changed
+37
-3
+37
-3
| --- src/backoffice.c | ||
| +++ src/backoffice.c | ||
| @@ -40,10 +40,11 @@ | ||
| 40 | 40 | */ |
| 41 | 41 | #include "config.h" |
| 42 | 42 | #include "backoffice.h" |
| 43 | 43 | #include <time.h> |
| 44 | 44 | #if defined(_WIN32) |
| 45 | +# include <process.h> | |
| 45 | 46 | # include <windows.h> |
| 46 | 47 | #else |
| 47 | 48 | # include <unistd.h> |
| 48 | 49 | # include <sys/types.h> |
| 49 | 50 | # include <signal.h> |
| @@ -171,17 +172,47 @@ | ||
| 171 | 172 | /* |
| 172 | 173 | ** Set an alarm to cause the process to exit after "x" seconds. This |
| 173 | 174 | ** prevents any kind of bug from keeping a backoffice process running |
| 174 | 175 | ** indefinitely. |
| 175 | 176 | */ |
| 176 | -#if !defined(_WIN32) | |
| 177 | 177 | static void backofficeSigalrmHandler(int x){ |
| 178 | - fossil_panic("backoffice timeout"); | |
| 178 | + fossil_panic("backoffice timeout (%d seconds)", x); | |
| 179 | +} | |
| 180 | +#if defined(_WIN32) | |
| 181 | +static void *threadHandle = NULL; | |
| 182 | +static void __stdcall backofficeWin32NoopApcProc(ULONG_PTR pArg){} /* NO-OP */ | |
| 183 | +static void backofficeWin32ThreadCleanup(){ | |
| 184 | + if( threadHandle!=NULL ){ | |
| 185 | + /* Queue no-op asynchronous procedure call to the sleeping | |
| 186 | + * thread. This will cause it to wake up with a non-zero | |
| 187 | + * return value. */ | |
| 188 | + if( QueueUserAPC(backofficeWin32NoopApcProc, threadHandle, 0) ){ | |
| 189 | + /* Wait for the thread to wake up and then exit. */ | |
| 190 | + WaitForSingleObject(threadHandle, INFINITE); | |
| 191 | + } | |
| 192 | + CloseHandle(threadHandle); | |
| 193 | + threadHandle = NULL; | |
| 194 | + } | |
| 195 | +} | |
| 196 | +static unsigned __stdcall backofficeWin32SigalrmThreadProc( | |
| 197 | + void *pArg /* IN: Pointer to integer number of whole seconds. */ | |
| 198 | +){ | |
| 199 | + int seconds = FOSSIL_PTR_TO_INT(pArg); | |
| 200 | + if( SleepEx((DWORD)seconds * 1000, TRUE)==0 ){ | |
| 201 | + backofficeSigalrmHandler(seconds); | |
| 202 | + } | |
| 203 | + _endthreadex(0); | |
| 204 | + return 0; /* NOT REACHED */ | |
| 179 | 205 | } |
| 180 | 206 | #endif |
| 181 | 207 | static void backofficeTimeout(int x){ |
| 182 | -#if !defined(_WIN32) | |
| 208 | +#if defined(_WIN32) | |
| 209 | + if( threadHandle!=NULL ) return; | |
| 210 | + threadHandle = (void*)_beginthreadex( | |
| 211 | + 0, 0, backofficeWin32SigalrmThreadProc, FOSSIL_INT_TO_PTR(x), 0, 0 | |
| 212 | + ); | |
| 213 | +#else | |
| 183 | 214 | signal(SIGALRM, backofficeSigalrmHandler); |
| 184 | 215 | alarm(x); |
| 185 | 216 | #endif |
| 186 | 217 | } |
| 187 | 218 | |
| @@ -293,10 +324,13 @@ | ||
| 293 | 324 | warningDelay *= 2; |
| 294 | 325 | } |
| 295 | 326 | sqlite3_sleep(1000); |
| 296 | 327 | } |
| 297 | 328 | } |
| 329 | +#if defined(_WIN32) | |
| 330 | + backofficeWin32ThreadCleanup(); | |
| 331 | +#endif | |
| 298 | 332 | return; |
| 299 | 333 | } |
| 300 | 334 | |
| 301 | 335 | /* |
| 302 | 336 | ** This routine runs to do the backoffice processing. When adding new |
| 303 | 337 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -40,10 +40,11 @@ | |
| 40 | */ |
| 41 | #include "config.h" |
| 42 | #include "backoffice.h" |
| 43 | #include <time.h> |
| 44 | #if defined(_WIN32) |
| 45 | # include <windows.h> |
| 46 | #else |
| 47 | # include <unistd.h> |
| 48 | # include <sys/types.h> |
| 49 | # include <signal.h> |
| @@ -171,17 +172,47 @@ | |
| 171 | /* |
| 172 | ** Set an alarm to cause the process to exit after "x" seconds. This |
| 173 | ** prevents any kind of bug from keeping a backoffice process running |
| 174 | ** indefinitely. |
| 175 | */ |
| 176 | #if !defined(_WIN32) |
| 177 | static void backofficeSigalrmHandler(int x){ |
| 178 | fossil_panic("backoffice timeout"); |
| 179 | } |
| 180 | #endif |
| 181 | static void backofficeTimeout(int x){ |
| 182 | #if !defined(_WIN32) |
| 183 | signal(SIGALRM, backofficeSigalrmHandler); |
| 184 | alarm(x); |
| 185 | #endif |
| 186 | } |
| 187 | |
| @@ -293,10 +324,13 @@ | |
| 293 | warningDelay *= 2; |
| 294 | } |
| 295 | sqlite3_sleep(1000); |
| 296 | } |
| 297 | } |
| 298 | return; |
| 299 | } |
| 300 | |
| 301 | /* |
| 302 | ** This routine runs to do the backoffice processing. When adding new |
| 303 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -40,10 +40,11 @@ | |
| 40 | */ |
| 41 | #include "config.h" |
| 42 | #include "backoffice.h" |
| 43 | #include <time.h> |
| 44 | #if defined(_WIN32) |
| 45 | # include <process.h> |
| 46 | # include <windows.h> |
| 47 | #else |
| 48 | # include <unistd.h> |
| 49 | # include <sys/types.h> |
| 50 | # include <signal.h> |
| @@ -171,17 +172,47 @@ | |
| 172 | /* |
| 173 | ** Set an alarm to cause the process to exit after "x" seconds. This |
| 174 | ** prevents any kind of bug from keeping a backoffice process running |
| 175 | ** indefinitely. |
| 176 | */ |
| 177 | static void backofficeSigalrmHandler(int x){ |
| 178 | fossil_panic("backoffice timeout (%d seconds)", x); |
| 179 | } |
| 180 | #if defined(_WIN32) |
| 181 | static void *threadHandle = NULL; |
| 182 | static void __stdcall backofficeWin32NoopApcProc(ULONG_PTR pArg){} /* NO-OP */ |
| 183 | static void backofficeWin32ThreadCleanup(){ |
| 184 | if( threadHandle!=NULL ){ |
| 185 | /* Queue no-op asynchronous procedure call to the sleeping |
| 186 | * thread. This will cause it to wake up with a non-zero |
| 187 | * return value. */ |
| 188 | if( QueueUserAPC(backofficeWin32NoopApcProc, threadHandle, 0) ){ |
| 189 | /* Wait for the thread to wake up and then exit. */ |
| 190 | WaitForSingleObject(threadHandle, INFINITE); |
| 191 | } |
| 192 | CloseHandle(threadHandle); |
| 193 | threadHandle = NULL; |
| 194 | } |
| 195 | } |
| 196 | static unsigned __stdcall backofficeWin32SigalrmThreadProc( |
| 197 | void *pArg /* IN: Pointer to integer number of whole seconds. */ |
| 198 | ){ |
| 199 | int seconds = FOSSIL_PTR_TO_INT(pArg); |
| 200 | if( SleepEx((DWORD)seconds * 1000, TRUE)==0 ){ |
| 201 | backofficeSigalrmHandler(seconds); |
| 202 | } |
| 203 | _endthreadex(0); |
| 204 | return 0; /* NOT REACHED */ |
| 205 | } |
| 206 | #endif |
| 207 | static void backofficeTimeout(int x){ |
| 208 | #if defined(_WIN32) |
| 209 | if( threadHandle!=NULL ) return; |
| 210 | threadHandle = (void*)_beginthreadex( |
| 211 | 0, 0, backofficeWin32SigalrmThreadProc, FOSSIL_INT_TO_PTR(x), 0, 0 |
| 212 | ); |
| 213 | #else |
| 214 | signal(SIGALRM, backofficeSigalrmHandler); |
| 215 | alarm(x); |
| 216 | #endif |
| 217 | } |
| 218 | |
| @@ -293,10 +324,13 @@ | |
| 324 | warningDelay *= 2; |
| 325 | } |
| 326 | sqlite3_sleep(1000); |
| 327 | } |
| 328 | } |
| 329 | #if defined(_WIN32) |
| 330 | backofficeWin32ThreadCleanup(); |
| 331 | #endif |
| 332 | return; |
| 333 | } |
| 334 | |
| 335 | /* |
| 336 | ** This routine runs to do the backoffice processing. When adding new |
| 337 |