kopia lustrzana https://gitlab.com/sane-project/backends
sanei_thread: Draft fixup for sanei_thread issues.
rodzic
9330bfdd83
commit
0b009ce12d
|
@ -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"));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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...*/
|
||||
|
|
|
@ -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...*/
|
||||
|
|
|
@ -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...*/
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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...*/
|
||||
|
|
|
@ -62,11 +62,40 @@
|
|||
|
||||
#ifdef USE_PTHREAD
|
||||
#include <pthread.h>
|
||||
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 */
|
||||
|
|
|
@ -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 .......................................................*/
|
||||
|
|
Ładowanie…
Reference in New Issue