88
99#include <stdio.h>
1010#include <stdlib.h>
11+ #include <string.h>
12+ #include <errno.h>
13+ #include <stdint.h>
1114#include "utils.h"
1215#include "sqlite3.h"
1316
14- #ifndef __linux__
1517#ifdef _WIN32
1618#include <windows.h>
1719#else
1820#include <pthread.h>
1921#endif
2022#define PEERS 5
21- #endif
2223
2324#ifdef CLOUDSYNC_LOAD_FROM_SOURCES
2425#include "cloudsync.h"
@@ -318,24 +319,29 @@ int test_report(const char *description, int rc){
318319 return rc ;
319320}
320321
321- #ifndef __linux__
322322#ifdef _WIN32
323323DWORD WINAPI worker (LPVOID arg ) {
324324#else
325325void * worker (void * arg ) {
326326#endif
327327 int thread_id = * (int * )arg ;
328+ int result = 0 ;
328329
329330 char description [32 ];
330331 snprintf (description , sizeof (description ), "%d/%d Peer Test" , thread_id + 1 , PEERS );
331- if (test_report (description , test_init (":memory:" , 1 ))){
332+ result = test_init (":memory:" , 1 );
333+ if (test_report (description , result )){
332334 printf ("PEER %d FAIL.\n" , thread_id + 1 );
333- exit (thread_id + 1 );
335+ // Return error code instead of exiting entire process
336+ return (void * )(intptr_t )(thread_id + 1 );
334337 }
335338
339+ #ifdef _WIN32
340+ return 0 ;
341+ #else
336342 return NULL ;
337- }
338343#endif
344+ }
339345
340346int main (void ) {
341347 int rc = SQLITE_OK ;
@@ -357,43 +363,92 @@ int main (void) {
357363
358364 remove (DB_PATH ); // remove the database file
359365
360- #ifndef __linux__
361366 #ifdef _WIN32
362367 HANDLE threads [PEERS ];
363368 #else
364369 pthread_t threads [PEERS ];
365370 #endif
366371 int thread_ids [PEERS ];
372+ int threads_created = 0 ;
373+ int thread_errors = 0 ;
374+
375+ // Initialize threads array to invalid values for cleanup
376+ #ifdef _WIN32
377+ for (int i = 0 ; i < PEERS ; i ++ ) {
378+ threads [i ] = NULL ;
379+ }
380+ #else
381+ memset (threads , 0 , sizeof (threads ));
382+ #endif
367383
384+ // Create threads with proper error handling
368385 for (int i = 0 ; i < PEERS ; i ++ ) {
369386 thread_ids [i ] = i ;
370387 #ifdef _WIN32
371388 threads [i ] = CreateThread (NULL , 0 , worker , & thread_ids [i ], 0 , NULL );
372389 if (threads [i ] == NULL ) {
373- fprintf (stderr , "CreateThread failed\n" );
374- return 1 ;
390+ fprintf (stderr , "CreateThread failed for thread %d: %lu\n" , i , GetLastError ());
391+ thread_errors ++ ;
392+ break ; // Stop creating more threads on failure
375393 }
376394 #else
377- if (pthread_create (& threads [i ], NULL , worker , & thread_ids [i ]) != 0 ) {
378- perror ("pthread_create" );
379- exit (1 );
395+ int pthread_result = pthread_create (& threads [i ], NULL , worker , & thread_ids [i ]);
396+ if (pthread_result != 0 ) {
397+ fprintf (stderr , "pthread_create failed for thread %d: %s\n" , i , strerror (pthread_result ));
398+ threads [i ] = 0 ; // Mark as invalid
399+ thread_errors ++ ;
400+ break ; // Stop creating more threads on failure
380401 }
381402 #endif
403+ threads_created ++ ;
382404 }
383405
384- // Wait for all threads to finish
406+ // Wait for all successfully created threads to finish and collect results
385407 #ifdef _WIN32
386- WaitForMultipleObjects (PEERS , threads , TRUE, INFINITE );
408+ if (threads_created > 0 ) {
409+ DWORD wait_result = WaitForMultipleObjects (threads_created , threads , TRUE, INFINITE );
410+ if (wait_result == WAIT_FAILED ) {
411+ fprintf (stderr , "WaitForMultipleObjects failed: %lu\n" , GetLastError ());
412+ thread_errors ++ ;
413+ }
414+ }
387415 #endif
388- for (int i = 0 ; i < PEERS ; i ++ ) {
416+
417+ // Join threads and collect exit codes
418+ for (int i = 0 ; i < threads_created ; i ++ ) {
389419 #ifdef _WIN32
390- CloseHandle (threads [i ]);
420+ if (threads [i ] != NULL ) {
421+ DWORD exit_code ;
422+ if (GetExitCodeThread (threads [i ], & exit_code ) && exit_code != 0 ) {
423+ thread_errors ++ ;
424+ printf ("Thread %d failed with exit code %lu\n" , i , exit_code );
425+ }
426+ CloseHandle (threads [i ]);
427+ threads [i ] = NULL ;
428+ }
391429 #else
392- pthread_join (threads [i ], NULL );
430+ if (threads [i ] != 0 ) {
431+ void * thread_result = NULL ;
432+ int join_result = pthread_join (threads [i ], & thread_result );
433+ if (join_result != 0 ) {
434+ fprintf (stderr , "pthread_join failed for thread %d: %s\n" , i , strerror (join_result ));
435+ thread_errors ++ ;
436+ } else if (thread_result != NULL ) {
437+ int exit_code = (int )(intptr_t )thread_result ;
438+ thread_errors ++ ;
439+ printf ("Thread %d failed with exit code %d\n" , i , exit_code );
440+ }
441+ threads [i ] = 0 ;
442+ }
393443 #endif
394444 }
395- #endif
396445
446+ // Update return code if any thread errors occurred
447+ if (thread_errors > 0 ) {
448+ printf ("Threading test failed: %d thread(s) had errors\n" , thread_errors );
449+ rc += thread_errors ;
450+ }
451+
397452 printf ("\n" );
398453 return rc ;
399454}
0 commit comments