From 0b009ce12d0d411cbdeb8ae2b9b709d557352596 Mon Sep 17 00:00:00 2001 From: Ralph Little Date: Sun, 28 Aug 2022 16:54:48 -0700 Subject: [PATCH 1/3] sanei_thread: Draft fixup for sanei_thread issues. --- backend/artec_eplus48u.c | 2 +- backend/coolscan.c | 5 +- backend/hp-handle.c | 66 +++++----- backend/hp3500.c | 2 +- backend/pixma/pixma.c | 8 +- backend/plustek.c | 2 +- backend/plustek_pp.c | 2 +- backend/snapscan.c | 2 +- backend/test.c | 2 +- backend/u12.c | 2 +- include/sane/sanei_thread.h | 64 +++++++++- sanei/sanei_thread.c | 246 ++++++++++++++++++++++++------------ 12 files changed, 272 insertions(+), 131 deletions(-) diff --git a/backend/artec_eplus48u.c b/backend/artec_eplus48u.c index e96e96f5a..b859e4137 100644 --- a/backend/artec_eplus48u.c +++ b/backend/artec_eplus48u.c @@ -3490,7 +3490,7 @@ do_cancel (Artec48U_Scanner * s, SANE_Bool closepipe) res = sanei_thread_waitpid (s->reader_pid, 0); alarm (0); - if (res != s->reader_pid) + if (!sanei_thread_pid_compare(res, s->reader_pid)) { XDBG ((1, "sanei_thread_waitpid() failed !\n")); } diff --git a/backend/coolscan.c b/backend/coolscan.c index 2aaef4e34..e3793a0cd 100644 --- a/backend/coolscan.c +++ b/backend/coolscan.c @@ -2033,8 +2033,9 @@ do_cancel (Coolscan_t * scanner) /* ensure child knows it's time to stop: */ sanei_thread_kill (scanner->reader_pid); - while (sanei_thread_waitpid(scanner->reader_pid, &exit_status) != - scanner->reader_pid ); + while (!sanei_thread_pid_compare(sanei_thread_waitpid(scanner->reader_pid, &exit_status), + scanner->reader_pid) ) + ; sanei_thread_invalidate (scanner->reader_pid); } diff --git a/backend/hp-handle.c b/backend/hp-handle.c index d7f781779..9db6921c3 100644 --- a/backend/hp-handle.c +++ b/backend/hp-handle.c @@ -90,7 +90,7 @@ struct hp_handle_s static hp_bool_t hp_handle_isScanning (HpHandle this) { - return this->reader_pid != 0; + return sanei_thread_is_valid(this->reader_pid); } /* @@ -157,7 +157,7 @@ hp_handle_startReader (HpHandle this, HpScsi scsi) int fds[2]; sigset_t old_set; - assert(this->reader_pid == 0); + assert(!sanei_thread_is_valid(this->reader_pid)); this->cancelled = 0; this->pipe_write_fd = this->pipe_read_fd = -1; @@ -178,39 +178,38 @@ hp_handle_startReader (HpHandle this, HpScsi scsi) /* Returning means to be in the parent or thread/fork failed */ this->reader_pid = sanei_thread_begin (this->child_forked ? reader_process : reader_thread, (void *) this); - if (this->reader_pid != 0) + if (sanei_thread_is_valid (this->reader_pid)) { /* Here we are in the parent */ sigprocmask(SIG_SETMASK, &old_set, 0); - if ( this->child_forked ) - { /* After fork(), parent must close writing end of pipe */ - DBG(3, "hp_handle_startReader: parent closes write end of pipe\n"); - close (this->pipe_write_fd); - this->pipe_write_fd = -1; - } + if (this->child_forked) + { /* After fork(), parent must close writing end of pipe */ + DBG (3, "hp_handle_startReader: parent closes write end of pipe\n"); + close (this->pipe_write_fd); + this->pipe_write_fd = -1; + } - if (!sanei_thread_is_valid (this->reader_pid)) - { - if ( !this->child_forked ) - { - close (this->pipe_write_fd); - this->pipe_write_fd = -1; - } - close (this->pipe_read_fd); - this->pipe_read_fd = -1; - - DBG(1, "hp_handle_startReader: fork() failed\n"); - - return SANE_STATUS_IO_ERROR; - } - - DBG(1, "start_reader: reader process %ld started\n", (long) this->reader_pid); + DBG (1, "start_reader: reader process %ld started\n", + sanei_thread_pid_to_long (this->reader_pid)); return SANE_STATUS_GOOD; } - DBG(3, "Unexpected return from sanei_thread_begin()\n"); - return SANE_STATUS_INVAL; + /* + * Error kicking off the reader. + * + */ + if (!this->child_forked) + { + close (this->pipe_write_fd); + this->pipe_write_fd = -1; + } + close (this->pipe_read_fd); + this->pipe_read_fd = -1; + + DBG (1, "hp_handle_startReader: fork()/thread start failed\n"); + + return SANE_STATUS_IO_ERROR; } static SANE_Status @@ -221,10 +220,11 @@ hp_handle_stopScan (HpHandle this) this->cancelled = 0; this->bytes_left = 0; - if (this->reader_pid) + if (sanei_thread_is_valid(this->reader_pid)) { int info; - DBG(3, "hp_handle_stopScan: killing child (%ld)\n", (long) this->reader_pid); + DBG(3, "hp_handle_stopScan: killing child (%ld)\n", + sanei_thread_pid_to_long(this->reader_pid)); sanei_thread_kill (this->reader_pid); sanei_thread_waitpid(this->reader_pid, &info); @@ -232,7 +232,7 @@ hp_handle_stopScan (HpHandle this) WIFEXITED(info) ? "exited, status" : "signalled, signal", WIFEXITED(info) ? WEXITSTATUS(info) : WTERMSIG(info)); close(this->pipe_read_fd); - this->reader_pid = 0; + sanei_thread_invalidate(this->reader_pid); if ( !FAILED( sanei_hp_scsi_new(&scsi, this->dev->sanedev.name)) ) { @@ -732,11 +732,11 @@ sanei_hp_handle_cancel (HpHandle this) /* Therefore the read might not return until it is interrupted. */ DBG(3,"sanei_hp_handle_cancel: compat flags: 0x%04x\n", (int)this->dev->compat); - if ( (this->reader_pid) - && (this->dev->compat & HP_COMPAT_OJ_1150C) ) + if (sanei_thread_is_valid (this->reader_pid) + && (this->dev->compat & HP_COMPAT_OJ_1150C)) { DBG(3,"sanei_hp_handle_cancel: send SIGTERM to child (%ld)\n", - (long) this->reader_pid); + sanei_thread_pid_to_long(this->reader_pid)); sanei_thread_kill(this->reader_pid); } } diff --git a/backend/hp3500.c b/backend/hp3500.c index acb09b630..12b4fd92b 100644 --- a/backend/hp3500.c +++ b/backend/hp3500.c @@ -966,7 +966,7 @@ attachScanner (const char *devicename) dev->devicename = strdup (devicename); dev->sfd = -1; dev->last_scan = 0; - dev->reader_pid = (SANE_Pid) -1; + sanei_thread_invalidate(dev->reader_pid); dev->pipe_r = dev->pipe_w = -1; dev->sane.name = dev->devicename; diff --git a/backend/pixma/pixma.c b/backend/pixma/pixma.c index 72385b286..deb44d89f 100644 --- a/backend/pixma/pixma.c +++ b/backend/pixma/pixma.c @@ -1228,7 +1228,7 @@ terminate_reader_task (pixma_sane_t * ss, int *exit_code) if (ss->sp.source != PIXMA_SOURCE_ADF && ss->sp.source != PIXMA_SOURCE_ADFDUP) ss->idle = SANE_TRUE; - if (result == pid) + if (sanei_thread_pid_compare(result, pid)) { if (exit_code) *exit_code = status; @@ -1261,7 +1261,8 @@ start_reader_task (pixma_sane_t * ss) if (sanei_thread_is_valid (ss->reader_taskid)) { PDBG (pixma_dbg - (1, "BUG:reader_taskid(%ld) != -1\n", (long) ss->reader_taskid)); + (1, "BUG:reader_taskid(%ld) != -1\n", + sanei_thread_pid_to_long(ss->reader_taskid))); terminate_reader_task (ss, NULL); } if (pipe (fds) == -1) @@ -1297,7 +1298,8 @@ start_reader_task (pixma_sane_t * ss) PDBG (pixma_dbg (1, "ERROR:unable to start reader task\n")); return PIXMA_ENOMEM; } - PDBG (pixma_dbg (3, "Reader task id=%ld (%s)\n", (long) pid, + PDBG (pixma_dbg (3, "Reader task id=%ld (%s)\n", + sanei_thread_pid_to_long(pid), (is_forked) ? "forked" : "threaded")); ss->reader_taskid = pid; return 0; diff --git a/backend/plustek.c b/backend/plustek.c index 96fd04faf..53acfd43b 100644 --- a/backend/plustek.c +++ b/backend/plustek.c @@ -591,7 +591,7 @@ do_cancel( Plustek_Scanner *scanner, SANE_Bool closepipe ) res = sanei_thread_waitpid( scanner->reader_pid, 0 ); alarm(0); - if( res != scanner->reader_pid ) { + if(!sanei_thread_pid_compare(res, scanner->reader_pid)) { DBG( _DBG_PROC,"sanei_thread_waitpid() failed !\n"); /* do it the hard way...*/ diff --git a/backend/plustek_pp.c b/backend/plustek_pp.c index af91c9979..890187119 100644 --- a/backend/plustek_pp.c +++ b/backend/plustek_pp.c @@ -493,7 +493,7 @@ static SANE_Status do_cancel( Plustek_Scanner *scanner, SANE_Bool closepipe ) res = sanei_thread_waitpid( scanner->reader_pid, 0 ); alarm(0); - if( res != scanner->reader_pid ) { + if( !sanei_thread_pid_compare(res, scanner->reader_pid) ) { DBG( _DBG_PROC,"sanei_thread_waitpid() failed !\n"); /* do it the hard way...*/ diff --git a/backend/snapscan.c b/backend/snapscan.c index 1298858b1..ae0ed631e 100644 --- a/backend/snapscan.c +++ b/backend/snapscan.c @@ -1893,7 +1893,7 @@ void sane_cancel (SANE_Handle h) res = sanei_thread_waitpid( pss->child, 0 ); alarm(0); - if( res != pss->child ) { + if( !sanei_thread_pid_compare(res, pss->child) ) { DBG( DL_MINOR_ERROR,"sanei_thread_waitpid() failed !\n"); /* do it the hard way...*/ diff --git a/backend/test.c b/backend/test.c index ea7329073..dc864f55d 100644 --- a/backend/test.c +++ b/backend/test.c @@ -1548,7 +1548,7 @@ finish_pass (Test_Device * test_device) SANE_Pid pid; DBG (2, "finish_pass: terminating reader process %ld\n", - (long) test_device->reader_pid); + sanei_thread_pid_to_long(test_device->reader_pid)); sanei_thread_kill (test_device->reader_pid); pid = sanei_thread_waitpid (test_device->reader_pid, &status); if (!sanei_thread_is_valid (pid)) diff --git a/backend/u12.c b/backend/u12.c index c7bc51aad..46bc42373 100644 --- a/backend/u12.c +++ b/backend/u12.c @@ -409,7 +409,7 @@ static SANE_Status do_cancel( U12_Scanner *scanner, SANE_Bool closepipe ) res = sanei_thread_waitpid( scanner->reader_pid, 0 ); alarm(0); - if( res != scanner->reader_pid ) { + if( !sanei_thread_pid_compare(res, scanner->reader_pid) ) { DBG( _DBG_PROC,"sanei_thread_waitpid() failed !\n"); /* do it the hard way...*/ diff --git a/include/sane/sanei_thread.h b/include/sane/sanei_thread.h index 72fd8fd29..e1f94e240 100644 --- a/include/sane/sanei_thread.h +++ b/include/sane/sanei_thread.h @@ -62,11 +62,40 @@ #ifdef USE_PTHREAD #include -typedef pthread_t SANE_Pid; -#else -typedef int SANE_Pid; #endif +/** Object used to identify a thread or process. + * + * SANE_Pid is defined with an additional validity flag + * since there is no cross-platform consensus on how to construct + * a pthread_t that can be reliably tested for validity. + * This is because pthread_t is opaque so we *cannot* make assumptions + * about what the underlying type is. It is often an int, sometimes + * a pointer and rarely an actual structure. + * + * Comparing pthread_t values for equality with == is not defined! + * Using pthread_equal() for pthread_t is recommended. + * For users of this API, we will provide a function sanei_thread_pid_compare() + * for comparing SANE_Pids and callers are urged to use it. + * + * In any case, comparing two pids with the same pthread_t will fail + * equality tests if either of the pids are marked as invalid. + * Two invalid pids are not equal. + * + */ +typedef struct +{ + SANE_Bool is_valid; + +#ifdef USE_PTHREAD + pthread_t pid; +#else + int pid; +#endif + +} SANE_Pid; + + /** Initialize sanei_thread. * * This function must be called before any other sanei_thread function. @@ -112,7 +141,7 @@ extern SANE_Bool sanei_thread_is_valid (SANE_Pid pid); * For details on the pthread_t type, see in particular Issue 6 of * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html */ -#define sanei_thread_invalidate(pid) ((pid) = (SANE_Pid)(-1)) +#define sanei_thread_invalidate(sane_pid) ((sane_pid).pid = SANE_FALSE) /** Initialize a SANE_Pid * @@ -194,4 +223,31 @@ extern SANE_Pid sanei_thread_waitpid (SANE_Pid pid, int *status); */ extern SANE_Status sanei_thread_get_status (SANE_Pid pid); + +/** Compare SANE_Pid for equality. + * + * @param pid1 - the id of the first task + * @param pid2 - the id of the second task + * + * @return + * - SANE_TRUE - if the SANE_Pids are the same (or equivalent). + * - SANE_FALSE - if the SANE_Pids are not the same (or not equivalent). + */ +extern SANE_Bool sanei_thread_pid_compare (SANE_Pid pid1, SANE_Pid pid2); + +/** Generate a long value to represent a SANE_Pid + * + * We cannot make any assumptions about what this long value represents since + * the underlying thread/process id on each platform may be different. + * + * It is handy for display purposes though, for example identifying which thread + * is being referred to in diagnostics. + * + * @param pid - the id of the task + * + * @return + * - long value of pid. + */ +extern long sanei_thread_pid_to_long( SANE_Pid pid ); + #endif /* sanei_thread_h */ diff --git a/sanei/sanei_thread.c b/sanei/sanei_thread.c index a5dcae154..24487e37a 100644 --- a/sanei/sanei_thread.c +++ b/sanei/sanei_thread.c @@ -117,16 +117,7 @@ sanei_thread_is_forked( void ) static void sanei_thread_set_invalid( SANE_Pid *pid ) { - -#ifdef WIN32 -#ifdef WINPTHREAD_API - *pid = (pthread_t) 0; -#else - pid->p = 0; -#endif -#else - *pid = (pthread_t) -1; -#endif + pid->pid = SANE_FALSE; } #endif @@ -134,40 +125,34 @@ sanei_thread_set_invalid( SANE_Pid *pid ) SANE_Bool sanei_thread_is_valid( SANE_Pid pid ) { - SANE_Bool rc = SANE_TRUE; - -#ifdef WIN32 -#ifdef WINPTHREAD_API - if (pid == 0) -#else - if (pid.p == 0) -#endif - rc = SANE_FALSE; -#else - if (pid == (SANE_Pid) -1) - rc = SANE_FALSE; -#endif - - return rc; + return pid.is_valid; } /* pthread_t is not an integer on all platform. Do our best to return * a PID-like value from structure. On platforms were it is an integer, * return that. + * + * Note: perhaps on platforms where pthread_t is a structure, compute a hash + * of the structure. It's not ideal but it is a thought. + * */ -static long +long sanei_thread_pid_to_long( SANE_Pid pid ) { int rc; + if (!pid.is_valid) + { + return 0l; + } #ifdef WIN32 #ifdef WINPTHREAD_API - rc = (long) pid; + rc = (long) pid.pid; #else - rc = pid.p; + rc = pid.pid.p; #endif #else - rc = (long) pid; + rc = (long) pid.pid; #endif return rc; @@ -176,18 +161,22 @@ sanei_thread_pid_to_long( SANE_Pid pid ) int sanei_thread_kill( SANE_Pid pid ) { + if (!pid.is_valid) + { + return -1; + } DBG(2, "sanei_thread_kill() will kill %ld\n", sanei_thread_pid_to_long(pid)); #ifdef USE_PTHREAD #if defined (__APPLE__) && defined (__MACH__) - return pthread_kill((pthread_t)pid, SIGUSR2); + return pthread_kill((pthread_t)pid.pid, SIGUSR2); #else - return pthread_cancel((pthread_t)pid); + return pthread_cancel((pthread_t)pid.pid); #endif #elif defined HAVE_OS2_H - return DosKillThread(pid); + return DosKillThread(pid.pid); #else - return kill( pid, SIGTERM ); + return kill( pid.pid, SIGTERM ); #endif } @@ -208,39 +197,52 @@ local_thread( void *arg ) /* * starts a new thread or process * parameters: - * star address of reader function + * + * func address of reader function * args pointer to scanner data structure * */ SANE_Pid sanei_thread_begin( int (*func)(void *args), void* args ) { - SANE_Pid pid; + SANE_Pid pid = {SANE_FALSE, -1}; td.func = func; td.func_data = args; - pid = _beginthread( local_thread, NULL, 1024*1024, (void*)&td ); - if ( pid == -1 ) { + pid.pid = _beginthread( local_thread, NULL, 1024*1024, (void*)&td ); + if ( pid.pid == -1 ) + { DBG( 1, "_beginthread() failed\n" ); - return -1; + return pid; } DBG( 2, "_beginthread() created thread %d\n", pid ); + pid.is_valid = SANE_TRUE; + return pid; } SANE_Pid sanei_thread_waitpid( SANE_Pid pid, int *status ) { - if (status) - *status = 0; - return pid; /* DosWaitThread( (TID*) &pid, DCWW_WAIT);*/ + if (!pid.is_valid) + { + return pid; + } + + if (status) + *status = 0; + return pid; /* DosWaitThread( (TID*) &pid, DCWW_WAIT);*/ } int sanei_thread_sendsig( SANE_Pid pid, int sig ) { + if (!pid.is_valid) + { + return -1; + } return 0; } @@ -268,42 +270,60 @@ local_thread( void *arg ) SANE_Pid sanei_thread_begin( int (*func)(void *args), void* args ) { - SANE_Pid pid; + SANE_Pid pid = {SANE_FALSE, B_OK}; td.func = func; td.func_data = args; - pid = spawn_thread( local_thread, "sane thread (yes they can be)", B_NORMAL_PRIORITY, (void*)&td ); - if ( pid < B_OK ) { + pid.pid = spawn_thread( local_thread, "sane thread (yes they can be)", B_NORMAL_PRIORITY, (void*)&td ); + if ( pid.pid < B_OK ) { DBG( 1, "spawn_thread() failed\n" ); - return -1; + return pid; } - if ( resume_thread(pid) < B_OK ) { + if ( resume_thread(pid.pid) < B_OK ) { DBG( 1, "resume_thread() failed\n" ); - return -1; + return pid; } DBG( 2, "spawn_thread() created thread %d\n", pid ); + pid.is_valid = SANE_TRUE; + return pid; } SANE_Pid sanei_thread_waitpid( SANE_Pid pid, int *status ) { - int32 st; - if ( wait_for_thread(pid, &st) < B_OK ) - return -1; - if ( status ) - *status = (int)st; - return pid; + int32 st; + + if (!pid.is_valid) + { + return pid; + } + + if ( wait_for_thread(pid.pid, &st) < B_OK ) + { + pid.is_valid = SANE_FALSE; + return pid; + } + if ( status ) + *status = (int)st; + + return pid; } int sanei_thread_sendsig( SANE_Pid pid, int sig ) { + if (!pid.is_valid) + { + return -1; + } + if (sig == SIGKILL) sig = SIGKILLTHR; - return kill(pid, sig); + + return kill(pid.pid, sig); } #else /* HAVE_OS2_H, __BEOS__ */ @@ -389,7 +409,7 @@ eval_wp_result( SANE_Pid pid, int wpres, int pf ) { int retval = SANE_STATUS_IO_ERROR; - if( wpres == pid ) { + if( wpres == pid.pid ) { if( WIFEXITED(pf)) { retval = WEXITSTATUS(pf); @@ -413,7 +433,8 @@ sanei_thread_begin( int (func)(void *args), void* args ) { #ifdef USE_PTHREAD int result; - pthread_t thread; + SANE_Pid thread; + #ifdef SIGPIPE struct sigaction act; @@ -434,27 +455,38 @@ sanei_thread_begin( int (func)(void *args), void* args ) td.func = func; td.func_data = args; - result = pthread_create( &thread, NULL, local_thread, &td ); + result = pthread_create( &thread.pid, NULL, local_thread, &td ); usleep( 1 ); - if ( result != 0 ) { + if ( result != 0 ) + { DBG( 1, "pthread_create() failed with %d\n", result ); sanei_thread_set_invalid(&thread); } else + { DBG( 2, "pthread_create() created thread %ld\n", sanei_thread_pid_to_long(thread) ); - - return (SANE_Pid)thread; -#else - SANE_Pid pid; - pid = fork(); - if( pid < 0 ) { - DBG( 1, "fork() failed\n" ); - return -1; + thread.is_valid = SANE_TRUE; } - if( pid == 0 ) { + return thread; +#else + SANE_Pid pid = {SANE_FALSE, 0}; + pid.pid = fork(); + if( pid.pid < 0 ) + { + DBG( 1, "fork() failed\n" ); + return pid; + } + + pid.is_valid = SANE_TRUE; + + /* + * If I am the child.... + * + */ + if( pid.pid == 0 ) { /* run in child context... */ int status = func( args ); @@ -473,10 +505,15 @@ sanei_thread_sendsig( SANE_Pid pid, int sig ) { DBG(2, "sanei_thread_sendsig() %d to thread (id=%ld)\n", sig, sanei_thread_pid_to_long(pid)); + + if (!pid.is_valid) + { + return -1; + } #ifdef USE_PTHREAD - return pthread_kill( (pthread_t)pid, sig ); + return pthread_kill( (pthread_t)pid.pid, sig ); #else - return kill( pid, sig ); + return kill( pid.pid, sig ); #endif } @@ -491,32 +528,55 @@ sanei_thread_waitpid( SANE_Pid pid, int *status ) SANE_Pid result = pid; int stat; + /* + * Can't join if the PID is invalid. + * + * Normally, we would assume that the below call would fail if + * the provided pid was invalid. However, we are now using a separate + * boolean flag in SANE_Pid so we must check this. + * + * We must assume that the caller is making rational assumptions when + * using SANE_Pid. You cannot assume that SANE_Pid is a pthread_t in + * particular. + * + */ + if (!pid.is_valid) + { + DBG(1, "sanei_thread_waitpid() - provided pid is invalid!\n"); + return pid; + } + stat = 0; - DBG(2, "sanei_thread_waitpid() - %ld\n", - sanei_thread_pid_to_long(pid)); + DBG(2, "sanei_thread_waitpid() - %ld\n", sanei_thread_pid_to_long(pid)); #ifdef USE_PTHREAD int rc; - rc = pthread_join( (pthread_t)pid, (void*)&ls ); + rc = pthread_join( pid.pid, (void*)&ls ); - if( 0 == rc ) { - if( PTHREAD_CANCELED == ls ) { + if( 0 == rc ) + { + if( PTHREAD_CANCELED == ls ) + { DBG(2, "* thread has been canceled!\n" ); stat = SANE_STATUS_GOOD; - } else { + } + else + { stat = *ls; } DBG(2, "* result = %d (%p)\n", stat, (void*)status ); result = pid; } - if ( EDEADLK == rc ) { - if ( (pthread_t)pid != pthread_self() ) { + if ( EDEADLK == rc ) + { + if (!pthread_equal(pid.pid, pthread_self())) + { /* call detach in any case to make sure that the thread resources * will be freed, when the thread has terminated */ DBG(2, "* detaching thread(%ld)\n", sanei_thread_pid_to_long(pid) ); - pthread_detach((pthread_t)pid); + pthread_detach(pid.pid); } } if (status) @@ -524,7 +584,7 @@ sanei_thread_waitpid( SANE_Pid pid, int *status ) restore_sigpipe(); #else - result = waitpid( pid, &ls, 0 ); + result = waitpid( pid.pid, &ls, 0 ); if((result < 0) && (errno == ECHILD)) { stat = SANE_STATUS_GOOD; result = pid; @@ -551,9 +611,9 @@ sanei_thread_get_status( SANE_Pid pid ) int ls, stat, result; stat = SANE_STATUS_IO_ERROR; - if( pid > 0 ) { - - result = waitpid( pid, &ls, WNOHANG ); + if (pid.is_valid && (pid.pid > 0) ) + { + result = waitpid( pid.pid, &ls, WNOHANG ); stat = eval_wp_result( pid, result, ls ); } @@ -561,4 +621,26 @@ sanei_thread_get_status( SANE_Pid pid ) #endif } +/* + * Note: for the case of where the underlying system pid is neither + * a pointer nor an integer, we should use an appropriate platform function + * for comparing pids. We will have to take each case as it comes. + * + */ +SANE_Bool +sanei_thread_pid_compare (SANE_Pid pid1, SANE_Pid pid2) +{ + if (!pid1.is_valid || !pid2.is_valid) + { + return SANE_FALSE; + } + +#if defined USE_PTHREAD + return pthread_equal(pid1.pid, pid2.pid)? SANE_TRUE: SANE_FALSE; +#else + return pid1.pid == pid2.pid; +#endif +} + + /* END sanei_thread.c .......................................................*/ From 1fc0928a733ccb3560e157766b44f35d583d8e3c Mon Sep 17 00:00:00 2001 From: Ralph Little Date: Mon, 29 Aug 2022 11:03:02 -0700 Subject: [PATCH 2/3] sanei_thread: correct silly error following quick review. --- sanei/sanei_thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sanei/sanei_thread.c b/sanei/sanei_thread.c index 24487e37a..d3005eacd 100644 --- a/sanei/sanei_thread.c +++ b/sanei/sanei_thread.c @@ -117,7 +117,7 @@ sanei_thread_is_forked( void ) static void sanei_thread_set_invalid( SANE_Pid *pid ) { - pid->pid = SANE_FALSE; + pid->is_valid = SANE_FALSE; } #endif From 06241f00af0c716dfbe0f1412a37768031c4c8f5 Mon Sep 17 00:00:00 2001 From: Ralph Little Date: Tue, 30 Aug 2022 21:05:12 -0700 Subject: [PATCH 3/3] sanei_thread: Corrected some additional mistakes. Major review and check is required followed by some extensive testing. We might also go for a different solution yet but we will see. --- include/sane/sanei_thread.h | 2 +- sanei/sanei_thread.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sane/sanei_thread.h b/include/sane/sanei_thread.h index e1f94e240..54e529318 100644 --- a/include/sane/sanei_thread.h +++ b/include/sane/sanei_thread.h @@ -141,7 +141,7 @@ extern SANE_Bool sanei_thread_is_valid (SANE_Pid pid); * For details on the pthread_t type, see in particular Issue 6 of * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html */ -#define sanei_thread_invalidate(sane_pid) ((sane_pid).pid = SANE_FALSE) +#define sanei_thread_invalidate(sane_pid) ((sane_pid).is_valid = SANE_FALSE) /** Initialize a SANE_Pid * diff --git a/sanei/sanei_thread.c b/sanei/sanei_thread.c index d3005eacd..f0ed886ea 100644 --- a/sanei/sanei_thread.c +++ b/sanei/sanei_thread.c @@ -117,7 +117,7 @@ sanei_thread_is_forked( void ) static void sanei_thread_set_invalid( SANE_Pid *pid ) { - pid->is_valid = SANE_FALSE; + sanei_thread_invalidate(*pid); } #endif