Have threads and processes exit more cleanly whenever possible.
This commit is contained in:
parent
aabef02912
commit
12f29b5076
|
@ -191,6 +191,7 @@ struct terminate_process_request
|
|||
{
|
||||
IN int handle; /* process handle to terminate */
|
||||
IN int exit_code; /* process exit code */
|
||||
OUT int self; /* suicide? */
|
||||
};
|
||||
|
||||
|
||||
|
@ -199,6 +200,8 @@ struct terminate_thread_request
|
|||
{
|
||||
IN int handle; /* thread handle to terminate */
|
||||
IN int exit_code; /* thread exit code */
|
||||
OUT int self; /* suicide? */
|
||||
OUT int last; /* last thread in this process? */
|
||||
};
|
||||
|
||||
|
||||
|
@ -1202,7 +1205,7 @@ enum request
|
|||
REQ_NB_REQUESTS
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 3
|
||||
#define SERVER_PROTOCOL_VERSION 4
|
||||
|
||||
/* ### make_requests end ### */
|
||||
/* Everything above this line is generated automatically by tools/make_requests */
|
||||
|
@ -1219,7 +1222,7 @@ enum request
|
|||
|
||||
extern unsigned int server_call_noerr( enum request req );
|
||||
extern unsigned int server_call_fd( enum request req, int fd_out, int *fd_in );
|
||||
extern void server_protocol_error( const char *err, ... );
|
||||
extern void server_protocol_error( const char *err, ... ) WINE_NORETURN;
|
||||
|
||||
/* get a pointer to the request buffer */
|
||||
static inline void * WINE_UNUSED get_req_buffer(void)
|
||||
|
|
|
@ -131,6 +131,6 @@ extern TEB *THREAD_IdToTEB( DWORD id );
|
|||
/* scheduler/sysdeps.c */
|
||||
extern int SYSDEPS_SpawnThread( TEB *teb );
|
||||
extern void SYSDEPS_SetCurThread( TEB *teb );
|
||||
extern void SYSDEPS_ExitThread(void);
|
||||
extern void SYSDEPS_ExitThread( int status ) WINE_NORETURN;
|
||||
|
||||
#endif /* __WINE_THREAD_H */
|
||||
|
|
|
@ -1223,8 +1223,8 @@ BOOL WINAPI EnumTimeFormatsW(TIMEFMT_ENUMPROCW lpTimeFmtEnumProc, LCID Loca
|
|||
#define EnumTimeFormats WINELIB_NAME_AW(EnumTimeFormats)
|
||||
BOOL WINAPI EqualSid(PSID, PSID);
|
||||
BOOL WINAPI EqualPrefixSid(PSID,PSID);
|
||||
VOID WINAPI ExitProcess(DWORD);
|
||||
VOID WINAPI ExitThread(DWORD);
|
||||
VOID WINAPI ExitProcess(DWORD) WINE_NORETURN;
|
||||
VOID WINAPI ExitThread(DWORD) WINE_NORETURN;
|
||||
DWORD WINAPI ExpandEnvironmentStringsA(LPCSTR,LPSTR,DWORD);
|
||||
DWORD WINAPI ExpandEnvironmentStringsW(LPCWSTR,LPWSTR,DWORD);
|
||||
#define ExpandEnvironmentStrings WINELIB_NAME_AW(ExpandEnvironmentStrings)
|
||||
|
|
|
@ -353,11 +353,13 @@ typedef LRESULT (CALLBACK *WNDPROC)(HWND,UINT,WPARAM,LPARAM);
|
|||
/* Macro for structure packing. */
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define WINE_PACKED __attribute__ ((packed))
|
||||
#define WINE_UNUSED __attribute__ ((unused))
|
||||
#define WINE_PACKED __attribute__((packed))
|
||||
#define WINE_UNUSED __attribute__((unused))
|
||||
#define WINE_NORETURN __attribute__((noreturn))
|
||||
#else
|
||||
#define WINE_PACKED /* nothing */
|
||||
#define WINE_UNUSED /* nothing */
|
||||
#define WINE_PACKED /* nothing */
|
||||
#define WINE_UNUSED /* nothing */
|
||||
#define WINE_NORETURN /* nothing */
|
||||
#endif
|
||||
|
||||
/* Macros to split words and longs. */
|
||||
|
|
|
@ -221,14 +221,13 @@ BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
|
|||
* Send DLL process detach notifications. See the comment about calling
|
||||
* sequence at MODULE_DllProcessAttach. Unless the bForceDetach flag
|
||||
* is set, only DLLs with zero refcount are notified.
|
||||
*
|
||||
* NOTE: Assumes that the process critical section is held!
|
||||
*
|
||||
*/
|
||||
void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved )
|
||||
{
|
||||
WINE_MODREF *wm;
|
||||
|
||||
EnterCriticalSection( &PROCESS_Current()->crit_section );
|
||||
|
||||
do
|
||||
{
|
||||
for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
|
||||
|
@ -248,6 +247,8 @@ void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved )
|
|||
break;
|
||||
}
|
||||
} while ( wm );
|
||||
|
||||
LeaveCriticalSection( &PROCESS_Current()->crit_section );
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
|
|
@ -77,17 +77,6 @@ static void fatal_perror( const char *err, ... )
|
|||
exit(1);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CLIENT_Die
|
||||
*
|
||||
* Die on protocol errors or socket close
|
||||
*/
|
||||
static void CLIENT_Die(void)
|
||||
{
|
||||
close( NtCurrentTeb()->socket );
|
||||
SYSDEPS_ExitThread();
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* server_protocol_error
|
||||
*/
|
||||
|
@ -99,7 +88,7 @@ void server_protocol_error( const char *err, ... )
|
|||
fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
|
||||
vfprintf( stderr, err, args );
|
||||
va_end( args );
|
||||
CLIENT_Die();
|
||||
SYSDEPS_ExitThread(1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -110,7 +99,7 @@ static void server_perror( const char *err )
|
|||
{
|
||||
fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
|
||||
perror( err );
|
||||
CLIENT_Die();
|
||||
SYSDEPS_ExitThread(1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,7 +115,7 @@ static void send_request( enum request req )
|
|||
return;
|
||||
if (ret == -1)
|
||||
{
|
||||
if (errno == EPIPE) CLIENT_Die();
|
||||
if (errno == EPIPE) SYSDEPS_ExitThread(0);
|
||||
server_perror( "sendmsg" );
|
||||
}
|
||||
server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
|
||||
|
@ -170,7 +159,7 @@ static void send_request_fd( enum request req, int fd )
|
|||
if ((ret = sendmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(req)) return;
|
||||
if (ret == -1)
|
||||
{
|
||||
if (errno == EPIPE) CLIENT_Die();
|
||||
if (errno == EPIPE) SYSDEPS_ExitThread(0);
|
||||
server_perror( "sendmsg" );
|
||||
}
|
||||
server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
|
||||
|
@ -190,15 +179,17 @@ static unsigned int wait_reply(void)
|
|||
{
|
||||
if ((ret = read( NtCurrentTeb()->socket, &res, sizeof(res) )) == sizeof(res))
|
||||
return res;
|
||||
if (!ret) break;
|
||||
if (ret == -1)
|
||||
{
|
||||
if (errno == EINTR) continue;
|
||||
if (errno == EPIPE) CLIENT_Die();
|
||||
if (errno == EPIPE) break;
|
||||
server_perror("read");
|
||||
}
|
||||
if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
|
||||
server_protocol_error( "partial msg received %d/%d\n", ret, sizeof(res) );
|
||||
}
|
||||
/* the server closed the connection; time to die... */
|
||||
SYSDEPS_ExitThread(0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -248,15 +239,17 @@ static unsigned int wait_reply_fd( int *fd )
|
|||
#endif
|
||||
return res;
|
||||
}
|
||||
if (!ret) break;
|
||||
if (ret == -1)
|
||||
{
|
||||
if (errno == EINTR) continue;
|
||||
if (errno == EPIPE) CLIENT_Die();
|
||||
if (errno == EPIPE) break;
|
||||
server_perror("recvmsg");
|
||||
}
|
||||
if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
|
||||
server_protocol_error( "partial seq received %d/%d\n", ret, sizeof(res) );
|
||||
}
|
||||
/* the server closed the connection; time to die... */
|
||||
SYSDEPS_ExitThread(0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -627,12 +627,16 @@ error:
|
|||
*/
|
||||
void WINAPI ExitProcess( DWORD status )
|
||||
{
|
||||
EnterCriticalSection( &PROCESS_Current()->crit_section );
|
||||
MODULE_DllProcessDetach( TRUE, (LPVOID)1 );
|
||||
LeaveCriticalSection( &PROCESS_Current()->crit_section );
|
||||
struct terminate_process_request *req = get_req_buffer();
|
||||
|
||||
MODULE_DllProcessDetach( TRUE, (LPVOID)1 );
|
||||
TASK_KillTask( 0 );
|
||||
TerminateProcess( GetCurrentProcess(), status );
|
||||
|
||||
/* send the exit code to the server */
|
||||
req->handle = GetCurrentProcess();
|
||||
req->exit_code = status;
|
||||
server_call( REQ_TERMINATE_PROCESS );
|
||||
exit( status );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -649,10 +653,12 @@ void WINAPI ExitProcess16( WORD status )
|
|||
*/
|
||||
BOOL WINAPI TerminateProcess( HANDLE handle, DWORD exit_code )
|
||||
{
|
||||
BOOL ret;
|
||||
struct terminate_process_request *req = get_req_buffer();
|
||||
req->handle = handle;
|
||||
req->exit_code = exit_code;
|
||||
return !server_call( REQ_TERMINATE_PROCESS );
|
||||
if ((ret = !server_call( REQ_TERMINATE_PROCESS )) && req->self) exit( exit_code );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ static void SYSDEPS_StartThread( TEB *teb )
|
|||
TerminateThread( GetCurrentThread(), GetExceptionCode() );
|
||||
}
|
||||
__ENDTRY
|
||||
SYSDEPS_ExitThread(); /* should never get here */
|
||||
SYSDEPS_ExitThread(0); /* should never get here */
|
||||
}
|
||||
|
||||
|
||||
|
@ -153,31 +153,31 @@ int SYSDEPS_SpawnThread( TEB *teb )
|
|||
|
||||
#ifdef linux
|
||||
if (clone( (int (*)(void *))SYSDEPS_StartThread, teb->stack_top,
|
||||
CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, teb ) < 0)
|
||||
CLONE_VM | CLONE_FS | SIGCHLD, teb ) < 0)
|
||||
return -1;
|
||||
/* FIXME: close the child socket in the parent process */
|
||||
/* close( thread->socket );*/
|
||||
close( teb->socket ); /* close the child socket in the parent */
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RFORK
|
||||
DWORD *sp = (DWORD *)teb->stack_top;
|
||||
*--sp = (DWORD)teb;
|
||||
void **sp = (void **)teb->stack_top;
|
||||
*--sp = teb;
|
||||
*--sp = 0;
|
||||
*--sp = (DWORD)SYSDEPS_StartThread;
|
||||
__asm__(
|
||||
"pushl %2;\n\t" /* RFPROC|RMEM */
|
||||
*--sp = SYSDEPS_StartThread;
|
||||
__asm__ __volatile__(
|
||||
"pushl %2;\n\t" /* RFPROC|RFMEM|RFFDG */
|
||||
"pushl $0;\n\t" /* 0 ? */
|
||||
"movl %1,%%eax;\n\t" /* SYS_rfork */
|
||||
".byte 0x9a; .long 0; .word 7;\n\t" /* lcall 7:0... FreeBSD syscall */
|
||||
"cmpl $0, %%edx;\n\t"
|
||||
"je 1f;\n\t"
|
||||
"movl %0,%%esp;\n\t" /* father -> new thread */
|
||||
"movl %0,%%esp;\n\t" /* child -> new thread */
|
||||
"ret;\n"
|
||||
"1:\n\t" /* child -> caller thread */
|
||||
"1:\n\t" /* parent -> caller thread */
|
||||
"addl $8,%%esp" :
|
||||
: "r" (sp), "g" (SYS_rfork), "g" (RFPROC|RFMEM)
|
||||
: "r" (sp), "g" (SYS_rfork), "g" (RFPROC|RFMEM|RFFDG)
|
||||
: "eax", "edx");
|
||||
close( teb->socket ); /* close the child socket in the parent */
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
|
@ -202,15 +202,14 @@ int SYSDEPS_SpawnThread( TEB *teb )
|
|||
* SYSDEPS_ExitThread
|
||||
*
|
||||
* Exit a running thread; must not return.
|
||||
* Must not make any reference to the thread structures (THDB etc.) as
|
||||
* they have already been deleted.
|
||||
*/
|
||||
void SYSDEPS_ExitThread(void)
|
||||
void SYSDEPS_ExitThread( int status )
|
||||
{
|
||||
#if !defined(__i386__) && defined(HAVE__LWP_CREATE)
|
||||
#ifdef HAVE__LWP_CREATE
|
||||
close( NtCurrentTeb()->socket );
|
||||
_lwp_exit();
|
||||
#endif
|
||||
_exit( 0 );
|
||||
_exit( status );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -336,8 +336,23 @@ HANDLE WINAPI CreateThread16( SECURITY_ATTRIBUTES *sa, DWORD stack,
|
|||
*/
|
||||
void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
|
||||
{
|
||||
MODULE_DllThreadDetach( NULL );
|
||||
TerminateThread( GetCurrentThread(), code );
|
||||
struct terminate_thread_request *req = get_req_buffer();
|
||||
|
||||
/* send the exit code to the server */
|
||||
req->handle = GetCurrentThread();
|
||||
req->exit_code = code;
|
||||
server_call( REQ_TERMINATE_THREAD );
|
||||
if (req->last)
|
||||
{
|
||||
MODULE_DllProcessDetach( TRUE, (LPVOID)1 );
|
||||
TASK_KillTask( 0 );
|
||||
exit( code );
|
||||
}
|
||||
else
|
||||
{
|
||||
MODULE_DllThreadDetach( NULL );
|
||||
SYSDEPS_ExitThread( code );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -590,10 +605,16 @@ BOOL WINAPI TerminateThread(
|
|||
HANDLE handle, /* [in] Handle to thread */
|
||||
DWORD exitcode) /* [in] Exit code for thread */
|
||||
{
|
||||
BOOL ret;
|
||||
struct terminate_thread_request *req = get_req_buffer();
|
||||
req->handle = handle;
|
||||
req->exit_code = exitcode;
|
||||
return !server_call( REQ_TERMINATE_THREAD );
|
||||
if ((ret = !server_call( REQ_TERMINATE_THREAD )) && req->self)
|
||||
{
|
||||
if (req->last) exit( exitcode );
|
||||
else SYSDEPS_ExitThread( exitcode );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -399,10 +399,16 @@ void resume_process( struct process *process )
|
|||
}
|
||||
|
||||
/* kill a process on the spot */
|
||||
void kill_process( struct process *process, int exit_code )
|
||||
static void kill_process( struct process *process, struct thread *skip, int exit_code )
|
||||
{
|
||||
while (process->thread_list)
|
||||
kill_thread( process->thread_list, exit_code );
|
||||
struct thread *thread = process->thread_list;
|
||||
while (thread)
|
||||
{
|
||||
struct thread *next = thread->proc_next;
|
||||
thread->exit_code = exit_code;
|
||||
if (thread != skip) kill_thread( thread, 1 );
|
||||
thread = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* kill all processes being debugged by a given thread */
|
||||
|
@ -416,7 +422,7 @@ void kill_debugged_processes( struct thread *debugger, int exit_code )
|
|||
process = process->next;
|
||||
if (!process) return;
|
||||
process->debugger = NULL;
|
||||
kill_process( process, exit_code );
|
||||
kill_process( process, NULL, exit_code );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -678,7 +684,8 @@ DECL_HANDLER(terminate_process)
|
|||
|
||||
if ((process = get_process_from_handle( req->handle, PROCESS_TERMINATE )))
|
||||
{
|
||||
kill_process( process, req->exit_code );
|
||||
req->self = (current->process == process);
|
||||
kill_process( process, current, req->exit_code );
|
||||
release_object( process );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,6 @@ extern void remove_process_thread( struct process *process,
|
|||
struct thread *thread );
|
||||
extern void suspend_process( struct process *process );
|
||||
extern void resume_process( struct process *process );
|
||||
extern void kill_process( struct process *process, int exit_code );
|
||||
extern void kill_debugged_processes( struct thread *debugger, int exit_code );
|
||||
extern struct process_snapshot *process_snap( int *count );
|
||||
|
||||
|
|
|
@ -117,21 +117,21 @@ static int attach_thread( struct thread *thread )
|
|||
}
|
||||
|
||||
/* detach from a Unix thread and kill it */
|
||||
void detach_thread( struct thread *thread )
|
||||
void detach_thread( struct thread *thread, int sig )
|
||||
{
|
||||
if (!thread->unix_pid) return;
|
||||
if (thread->attached)
|
||||
{
|
||||
/* make sure it is stopped */
|
||||
if (!(thread->suspend + thread->process->suspend)) stop_thread( thread );
|
||||
kill( thread->unix_pid, SIGTERM );
|
||||
if (sig) kill( thread->unix_pid, sig );
|
||||
if (debug_level) fprintf( stderr, "%08x: *detached*\n", (unsigned int)thread );
|
||||
ptrace( PTRACE_DETACH, thread->unix_pid, 1, SIGTERM );
|
||||
ptrace( PTRACE_DETACH, thread->unix_pid, 1, sig );
|
||||
thread->attached = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
kill( thread->unix_pid, SIGTERM );
|
||||
if (sig) kill( thread->unix_pid, sig );
|
||||
if (thread->suspend + thread->process->suspend) continue_thread( thread );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,7 +98,8 @@ void fatal_protocol_error( struct thread *thread, const char *err, ... )
|
|||
fprintf( stderr, "Protocol error:%p: ", thread );
|
||||
vfprintf( stderr, err, args );
|
||||
va_end( args );
|
||||
kill_thread( thread, PROTOCOL_ERROR );
|
||||
thread->exit_code = 1;
|
||||
kill_thread( thread, 1 );
|
||||
}
|
||||
|
||||
/* die on a fatal error */
|
||||
|
@ -193,12 +194,13 @@ void read_request( struct thread *thread )
|
|||
if (ret == -1)
|
||||
{
|
||||
perror("recvmsg");
|
||||
kill_thread( thread, BROKEN_PIPE );
|
||||
thread->exit_code = 1;
|
||||
kill_thread( thread, 1 );
|
||||
return;
|
||||
}
|
||||
if (!ret) /* closed pipe */
|
||||
{
|
||||
kill_thread( thread, BROKEN_PIPE );
|
||||
kill_thread( thread, 0 );
|
||||
return;
|
||||
}
|
||||
fatal_protocol_error( thread, "partial message received %d/%d\n", ret, sizeof(req) );
|
||||
|
@ -212,7 +214,6 @@ int write_request( struct thread *thread )
|
|||
if (thread->pass_fd == -1)
|
||||
{
|
||||
ret = write( thread->obj.fd, &thread->error, sizeof(thread->error) );
|
||||
if (ret == sizeof(thread->error)) goto ok;
|
||||
}
|
||||
else /* we have an fd to send */
|
||||
{
|
||||
|
@ -231,20 +232,33 @@ int write_request( struct thread *thread )
|
|||
ret = sendmsg( thread->obj.fd, &msghdr, 0 );
|
||||
close( thread->pass_fd );
|
||||
thread->pass_fd = -1;
|
||||
if (ret == sizeof(thread->error)) goto ok;
|
||||
}
|
||||
if (ret == sizeof(thread->error))
|
||||
{
|
||||
set_select_events( &thread->obj, POLLIN );
|
||||
return 1;
|
||||
}
|
||||
if (ret == -1)
|
||||
{
|
||||
if (errno == EWOULDBLOCK) return 0; /* not a fatal error */
|
||||
if (errno != EPIPE) perror("sendmsg");
|
||||
if (errno == EPIPE)
|
||||
{
|
||||
kill_thread( thread, 0 ); /* normal death */
|
||||
}
|
||||
else
|
||||
{
|
||||
perror("sendmsg");
|
||||
thread->exit_code = 1;
|
||||
kill_thread( thread, 1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
thread->exit_code = 1;
|
||||
kill_thread( thread, 1 );
|
||||
fprintf( stderr, "Partial message sent %d/%d\n", ret, sizeof(thread->error) );
|
||||
}
|
||||
else fprintf( stderr, "Partial message sent %d/%d\n", ret, sizeof(thread->error) );
|
||||
kill_thread( thread, BROKEN_PIPE );
|
||||
return -1;
|
||||
|
||||
ok:
|
||||
set_select_events( &thread->obj, POLLIN );
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void master_socket_dump( struct object *obj, int verbose )
|
||||
|
|
|
@ -16,11 +16,6 @@
|
|||
/* max request length */
|
||||
#define MAX_REQUEST_LENGTH 8192
|
||||
|
||||
/* exit code passed to remove_client on communication error */
|
||||
#define OUT_OF_MEMORY -1
|
||||
#define BROKEN_PIPE -2
|
||||
#define PROTOCOL_ERROR -3
|
||||
|
||||
/* request handler definition */
|
||||
#define DECL_HANDLER(name) void req_##name( struct name##_request *req )
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ struct thread *create_thread( int fd, struct process *process, int suspend )
|
|||
thread->pass_fd = -1;
|
||||
thread->state = RUNNING;
|
||||
thread->attached = 0;
|
||||
thread->exit_code = STILL_ACTIVE;
|
||||
thread->exit_code = 0;
|
||||
thread->next = NULL;
|
||||
thread->prev = NULL;
|
||||
thread->priority = THREAD_PRIORITY_NORMAL;
|
||||
|
@ -175,7 +175,7 @@ void thread_poll_event( struct object *obj, int event )
|
|||
struct thread *thread = (struct thread *)obj;
|
||||
assert( obj->ops == &thread_ops );
|
||||
|
||||
if (event & (POLLERR | POLLHUP)) kill_thread( thread, BROKEN_PIPE );
|
||||
if (event & (POLLERR | POLLHUP)) kill_thread( thread, 0 );
|
||||
else
|
||||
{
|
||||
if (event & POLLOUT) write_request( thread );
|
||||
|
@ -556,20 +556,25 @@ static void get_selector_entry( struct thread *thread, int entry,
|
|||
}
|
||||
|
||||
/* kill a thread on the spot */
|
||||
void kill_thread( struct thread *thread, int exit_code )
|
||||
void kill_thread( struct thread *thread, int violent_death )
|
||||
{
|
||||
if (thread->state == TERMINATED) return; /* already killed */
|
||||
thread->state = TERMINATED;
|
||||
thread->exit_code = exit_code;
|
||||
if (current == thread) current = NULL;
|
||||
if (debug_level)
|
||||
fprintf( stderr,"%08x: *killed* exit_code=%d\n", (unsigned int)thread, exit_code );
|
||||
if (thread->wait) end_wait( thread );
|
||||
fprintf( stderr,"%08x: *killed* exit_code=%d\n",
|
||||
(unsigned int)thread, thread->exit_code );
|
||||
if (thread->wait)
|
||||
{
|
||||
end_wait( thread );
|
||||
/* if it is waiting on the socket, we don't need to send a SIGTERM */
|
||||
violent_death = 0;
|
||||
}
|
||||
debug_exit_thread( thread );
|
||||
abandon_mutexes( thread );
|
||||
remove_process_thread( thread->process, thread );
|
||||
wake_up( &thread->obj, 0 );
|
||||
detach_thread( thread );
|
||||
detach_thread( thread, violent_death ? SIGTERM : 0 );
|
||||
remove_select_user( &thread->obj );
|
||||
release_object( thread );
|
||||
}
|
||||
|
@ -639,9 +644,17 @@ DECL_HANDLER(terminate_thread)
|
|||
{
|
||||
struct thread *thread;
|
||||
|
||||
req->self = 0;
|
||||
req->last = 0;
|
||||
if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
|
||||
{
|
||||
kill_thread( thread, req->exit_code );
|
||||
thread->exit_code = req->exit_code;
|
||||
if (thread != current) kill_thread( thread, 1 );
|
||||
else
|
||||
{
|
||||
req->self = 1;
|
||||
req->last = (thread->process->running_threads == 1);
|
||||
}
|
||||
release_object( thread );
|
||||
}
|
||||
}
|
||||
|
@ -654,7 +667,7 @@ DECL_HANDLER(get_thread_info)
|
|||
if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
|
||||
{
|
||||
req->tid = thread;
|
||||
req->exit_code = thread->exit_code;
|
||||
req->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STILL_ACTIVE;
|
||||
req->priority = thread->priority;
|
||||
release_object( thread );
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ extern void suspend_all_threads( void );
|
|||
extern void resume_all_threads( void );
|
||||
extern int add_queue( struct object *obj, struct wait_queue_entry *entry );
|
||||
extern void remove_queue( struct object *obj, struct wait_queue_entry *entry );
|
||||
extern void kill_thread( struct thread *thread, int exit_code );
|
||||
extern void kill_thread( struct thread *thread, int violent_death );
|
||||
extern void wake_up( struct object *obj, int max );
|
||||
extern int sleep_on( int count, struct object *objects[], int flags,
|
||||
int timeout, sleep_reply func );
|
||||
|
@ -85,7 +85,7 @@ extern void sigchld_handler();
|
|||
extern void wait4_thread( struct thread *thread, int signal );
|
||||
extern void stop_thread( struct thread *thread );
|
||||
extern void continue_thread( struct thread *thread );
|
||||
extern void detach_thread( struct thread *thread );
|
||||
extern void detach_thread( struct thread *thread, int sig );
|
||||
extern int suspend_for_ptrace( struct thread *thread );
|
||||
extern int read_thread_int( struct thread *thread, const int *addr, int *data );
|
||||
extern int write_thread_int( struct thread *thread, int *addr, int data, unsigned int mask );
|
||||
|
|
|
@ -297,12 +297,23 @@ static void dump_terminate_process_request( const struct terminate_process_reque
|
|||
fprintf( stderr, " exit_code=%d", req->exit_code );
|
||||
}
|
||||
|
||||
static void dump_terminate_process_reply( const struct terminate_process_request *req )
|
||||
{
|
||||
fprintf( stderr, " self=%d", req->self );
|
||||
}
|
||||
|
||||
static void dump_terminate_thread_request( const struct terminate_thread_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%d,", req->handle );
|
||||
fprintf( stderr, " exit_code=%d", req->exit_code );
|
||||
}
|
||||
|
||||
static void dump_terminate_thread_reply( const struct terminate_thread_request *req )
|
||||
{
|
||||
fprintf( stderr, " self=%d,", req->self );
|
||||
fprintf( stderr, " last=%d", req->last );
|
||||
}
|
||||
|
||||
static void dump_get_process_info_request( const struct get_process_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%d", req->handle );
|
||||
|
@ -1366,8 +1377,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_init_process_done_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_thread_buffer_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_terminate_process_reply,
|
||||
(dump_func)dump_terminate_thread_reply,
|
||||
(dump_func)dump_get_process_info_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_thread_info_reply,
|
||||
|
|
Loading…
Reference in New Issue