Generate CREATE_PROCESS/THREAD debug events internally in the server.
This commit is contained in:
parent
ca3c9ba4ec
commit
ff81d78708
|
@ -170,8 +170,6 @@ extern void PROCESS_WalkProcess( void );
|
|||
|
||||
/* scheduler/debugger.c */
|
||||
extern DWORD DEBUG_SendExceptionEvent( EXCEPTION_RECORD *rec, BOOL first_chance, CONTEXT *ctx );
|
||||
extern DWORD DEBUG_SendCreateProcessEvent( HFILE file, HMODULE module, void *entry );
|
||||
extern DWORD DEBUG_SendCreateThreadEvent( void *entry );
|
||||
extern DWORD DEBUG_SendLoadDLLEvent( HFILE file, HMODULE module, LPSTR *name );
|
||||
extern DWORD DEBUG_SendUnloadDLLEvent( HMODULE module );
|
||||
|
||||
|
|
|
@ -165,7 +165,8 @@ struct init_process_request
|
|||
/* Signal the end of the process initialization */
|
||||
struct init_process_done_request
|
||||
{
|
||||
IN int dummy;
|
||||
IN void* module; /* main module base address */
|
||||
IN void* entry; /* process entry point */
|
||||
};
|
||||
|
||||
|
||||
|
@ -174,9 +175,7 @@ struct init_thread_request
|
|||
{
|
||||
IN int unix_pid; /* Unix pid of new thread */
|
||||
IN void* teb; /* TEB of new thread (in thread address space) */
|
||||
OUT void* pid; /* process id of the new thread's process */
|
||||
OUT void* tid; /* thread id of the new thread */
|
||||
OUT int boot; /* is this the boot thread? */
|
||||
IN void* entry; /* thread entry point (in thread address space) */
|
||||
};
|
||||
|
||||
|
||||
|
@ -185,7 +184,9 @@ struct init_thread_request
|
|||
/* created thread gets (without having to request it) */
|
||||
struct get_thread_buffer_request
|
||||
{
|
||||
IN int dummy;
|
||||
OUT void* pid; /* process id of the new thread's process */
|
||||
OUT void* tid; /* thread id of the new thread */
|
||||
OUT int boot; /* is this the boot thread? */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -453,6 +453,7 @@ int CLIENT_InitServer(void)
|
|||
*/
|
||||
int CLIENT_InitThread(void)
|
||||
{
|
||||
struct get_thread_buffer_request *first_req;
|
||||
struct init_thread_request *req;
|
||||
TEB *teb = NtCurrentTeb();
|
||||
int fd;
|
||||
|
@ -463,16 +464,17 @@ int CLIENT_InitThread(void)
|
|||
teb->buffer = mmap( 0, teb->buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
|
||||
close( fd );
|
||||
if (teb->buffer == (void*)-1) server_perror( "mmap" );
|
||||
first_req = teb->buffer;
|
||||
teb->process->server_pid = first_req->pid;
|
||||
teb->tid = first_req->tid;
|
||||
if (first_req->boot) boot_thread_id = teb->tid;
|
||||
else if (boot_thread_id == teb->tid) boot_thread_id = 0;
|
||||
|
||||
req = get_req_buffer();
|
||||
req = teb->buffer;
|
||||
req->unix_pid = getpid();
|
||||
req->teb = teb;
|
||||
if (server_call( REQ_INIT_THREAD )) return -1;
|
||||
teb->process->server_pid = req->pid;
|
||||
teb->tid = req->tid;
|
||||
if (req->boot) boot_thread_id = req->tid;
|
||||
else if (boot_thread_id == req->tid) boot_thread_id = 0;
|
||||
return 0;
|
||||
req->entry = teb->entry_point;
|
||||
return server_call_noerr( REQ_INIT_THREAD );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include "winerror.h"
|
||||
#include "process.h"
|
||||
#include "thread.h"
|
||||
#include "server.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
|
@ -22,7 +22,6 @@ DEFAULT_DEBUG_CHANNEL(debugstr);
|
|||
DWORD DEBUG_SendExceptionEvent( EXCEPTION_RECORD *rec, BOOL first_chance, CONTEXT *context )
|
||||
{
|
||||
int i;
|
||||
DWORD ret = 0;
|
||||
struct send_debug_event_request *req = get_req_buffer();
|
||||
|
||||
req->event.code = EXCEPTION_DEBUG_EVENT;
|
||||
|
@ -35,58 +34,9 @@ DWORD DEBUG_SendExceptionEvent( EXCEPTION_RECORD *rec, BOOL first_chance, CONTEX
|
|||
req->event.info.exception.context = *context;
|
||||
for (i = 0; i < req->event.info.exception.nb_params; i++)
|
||||
req->event.info.exception.params[i] = rec->ExceptionInformation[i];
|
||||
if (!server_call( REQ_SEND_DEBUG_EVENT ))
|
||||
{
|
||||
ret = req->status;
|
||||
if (!server_call_noerr( REQ_SEND_DEBUG_EVENT ))
|
||||
*context = req->event.info.exception.context;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* DEBUG_SendCreateProcessEvent
|
||||
*
|
||||
* Send an CREATE_PROCESS_DEBUG_EVENT event to the current process debugger.
|
||||
* Must be called from the context of the new process.
|
||||
*/
|
||||
DWORD DEBUG_SendCreateProcessEvent( HFILE file, HMODULE module, void *entry )
|
||||
{
|
||||
DWORD ret = 0;
|
||||
struct send_debug_event_request *req = get_req_buffer();
|
||||
|
||||
req->event.code = CREATE_PROCESS_DEBUG_EVENT;
|
||||
req->event.info.create_process.file = file;
|
||||
req->event.info.create_process.process = 0; /* will be filled by server */
|
||||
req->event.info.create_process.thread = 0; /* will be filled by server */
|
||||
req->event.info.create_process.base = (void *)module;
|
||||
req->event.info.create_process.dbg_offset = 0; /* FIXME */
|
||||
req->event.info.create_process.dbg_size = 0; /* FIXME */
|
||||
req->event.info.create_process.teb = NtCurrentTeb();
|
||||
req->event.info.create_process.start = entry;
|
||||
req->event.info.create_process.name = 0; /* FIXME */
|
||||
req->event.info.create_process.unicode = 0; /* FIXME */
|
||||
if (!server_call( REQ_SEND_DEBUG_EVENT )) ret = req->status;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* DEBUG_SendCreateThreadEvent
|
||||
*
|
||||
* Send an CREATE_THREAD_DEBUG_EVENT event to the current process debugger.
|
||||
* Must be called from the context of the new thread.
|
||||
*/
|
||||
DWORD DEBUG_SendCreateThreadEvent( void *entry )
|
||||
{
|
||||
DWORD ret = 0;
|
||||
struct send_debug_event_request *req = get_req_buffer();
|
||||
|
||||
req->event.code = CREATE_THREAD_DEBUG_EVENT;
|
||||
req->event.info.create_thread.handle = 0; /* will be filled by server */
|
||||
req->event.info.create_thread.teb = NtCurrentTeb();
|
||||
req->event.info.create_thread.start = entry;
|
||||
if (!server_call( REQ_SEND_DEBUG_EVENT )) ret = req->status;
|
||||
return ret;
|
||||
return req->status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -97,7 +47,6 @@ DWORD DEBUG_SendCreateThreadEvent( void *entry )
|
|||
*/
|
||||
DWORD DEBUG_SendLoadDLLEvent( HFILE file, HMODULE module, LPSTR *name )
|
||||
{
|
||||
DWORD ret = 0;
|
||||
struct send_debug_event_request *req = get_req_buffer();
|
||||
|
||||
req->event.code = LOAD_DLL_DEBUG_EVENT;
|
||||
|
@ -107,8 +56,8 @@ DWORD DEBUG_SendLoadDLLEvent( HFILE file, HMODULE module, LPSTR *name )
|
|||
req->event.info.load_dll.dbg_size = 0; /* FIXME */
|
||||
req->event.info.load_dll.name = name;
|
||||
req->event.info.load_dll.unicode = 0;
|
||||
if (!server_call( REQ_SEND_DEBUG_EVENT )) ret = req->status;
|
||||
return ret;
|
||||
server_call_noerr( REQ_SEND_DEBUG_EVENT );
|
||||
return req->status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -119,13 +68,12 @@ DWORD DEBUG_SendLoadDLLEvent( HFILE file, HMODULE module, LPSTR *name )
|
|||
*/
|
||||
DWORD DEBUG_SendUnloadDLLEvent( HMODULE module )
|
||||
{
|
||||
DWORD ret = 0;
|
||||
struct send_debug_event_request *req = get_req_buffer();
|
||||
|
||||
req->event.code = UNLOAD_DLL_DEBUG_EVENT;
|
||||
req->event.info.unload_dll.base = (void *)module;
|
||||
if (!server_call( REQ_SEND_DEBUG_EVENT )) ret = req->status;
|
||||
return ret;
|
||||
server_call_noerr( REQ_SEND_DEBUG_EVENT );
|
||||
return req->status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -155,6 +103,9 @@ BOOL WINAPI WaitForDebugEvent( LPDEBUG_EVENT event, DWORD timeout )
|
|||
event->dwThreadId = (DWORD)req->tid;
|
||||
switch(req->event.code)
|
||||
{
|
||||
case 0: /* timeout */
|
||||
SetLastError( ERROR_SEM_TIMEOUT );
|
||||
return FALSE;
|
||||
case EXCEPTION_DEBUG_EVENT:
|
||||
event->u.Exception.ExceptionRecord.ExceptionCode = req->event.info.exception.code;
|
||||
event->u.Exception.ExceptionRecord.ExceptionFlags = req->event.info.exception.flags;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "server.h"
|
||||
#include "options.h"
|
||||
#include "callback.h"
|
||||
#include "debugger.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(process)
|
||||
|
@ -371,6 +370,7 @@ BOOL PROCESS_Init( BOOL win32 )
|
|||
*/
|
||||
void PROCESS_Start(void)
|
||||
{
|
||||
struct init_process_done_request *req = get_req_buffer();
|
||||
UINT cmdShow = SW_SHOWNORMAL;
|
||||
LPTHREAD_START_ROUTINE entry = NULL;
|
||||
PDB *pdb = PROCESS_Current();
|
||||
|
@ -452,16 +452,15 @@ void PROCESS_Start(void)
|
|||
PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0, 0 );
|
||||
|
||||
/* Signal the parent process to continue */
|
||||
req->module = (void *)pModule->module32;
|
||||
req->entry = entry;
|
||||
server_call( REQ_INIT_PROCESS_DONE );
|
||||
|
||||
/* Send all required start-up debugger events */
|
||||
if ( type == PROC_WIN32 && (pdb->flags & PDB32_DEBUGGED) )
|
||||
{
|
||||
EnterCriticalSection( &pdb->crit_section );
|
||||
|
||||
DEBUG_SendCreateProcessEvent( -1 /*FIXME*/, pModule->module32, entry );
|
||||
MODULE_SendLoadDLLEvents();
|
||||
|
||||
LeaveCriticalSection( &pdb->crit_section );
|
||||
}
|
||||
|
||||
|
@ -479,10 +478,6 @@ void PROCESS_Start(void)
|
|||
LeaveCriticalSection( &pdb->crit_section );
|
||||
}
|
||||
|
||||
/* If requested, add entry point breakpoint */
|
||||
if ( Options.debug || (pdb->flags & PDB32_DEBUGGED) )
|
||||
DEBUG_AddTaskEntryBreakpoint( pdb->task );
|
||||
|
||||
/* Call UserSignalProc ( USIG_PROCESS_RUNNING ... ) only for non-GUI win32 apps */
|
||||
if ( type != PROC_WIN16 && (pdb->flags & PDB32_CONSOLE_PROC))
|
||||
PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0, 0 );
|
||||
|
|
|
@ -276,9 +276,6 @@ static void THREAD_Start(void)
|
|||
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, (DWORD)NtCurrentTeb()->tid, 0 );
|
||||
PE_InitTls();
|
||||
MODULE_DllThreadAttach( NULL );
|
||||
|
||||
if (NtCurrentTeb()->process->flags & PDB32_DEBUGGED) DEBUG_SendCreateThreadEvent( func );
|
||||
|
||||
ExitThread( func( NtCurrentTeb()->entry_arg ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -97,30 +97,43 @@ static int fill_debug_event( struct thread *debugger, struct thread *thread,
|
|||
/* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
|
||||
THREAD_ALL_ACCESS, FALSE )) == -1)
|
||||
return 0;
|
||||
event->data.info.create_thread.teb = thread->teb;
|
||||
event->data.info.create_thread.start = thread->entry;
|
||||
break;
|
||||
case CREATE_PROCESS_DEBUG_EVENT:
|
||||
if ((handle = event->data.info.create_process.file) != -1)
|
||||
{
|
||||
if ((handle = duplicate_handle( thread->process, handle, debugger->process,
|
||||
GENERIC_READ, FALSE, 0 )) == -1)
|
||||
return 0;
|
||||
event->data.info.create_process.file = handle;
|
||||
}
|
||||
if ((event->data.info.create_process.process = alloc_handle( debugger->process, thread->process,
|
||||
/* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
|
||||
PROCESS_ALL_ACCESS, FALSE )) == -1)
|
||||
{
|
||||
if (handle != -1) close_handle( debugger->process, handle );
|
||||
if ((handle = alloc_handle( debugger->process, thread->process,
|
||||
/* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
|
||||
PROCESS_ALL_ACCESS, FALSE )) == -1)
|
||||
return 0;
|
||||
}
|
||||
if ((event->data.info.create_process.thread = alloc_handle( debugger->process, thread,
|
||||
event->data.info.create_process.process = handle;
|
||||
|
||||
if ((handle = alloc_handle( debugger->process, thread,
|
||||
/* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
|
||||
THREAD_ALL_ACCESS, FALSE )) == -1)
|
||||
THREAD_ALL_ACCESS, FALSE )) == -1)
|
||||
{
|
||||
if (handle != -1) close_handle( debugger->process, handle );
|
||||
close_handle( debugger->process, event->data.info.create_process.process );
|
||||
return 0;
|
||||
}
|
||||
event->data.info.create_process.thread = handle;
|
||||
|
||||
handle = -1;
|
||||
if (thread->process->exe_file &&
|
||||
((handle = alloc_handle( debugger->process, thread->process->exe_file,
|
||||
/* the doc says write access too, but this doesn't seem a good idea */
|
||||
GENERIC_READ, FALSE )) == -1))
|
||||
{
|
||||
close_handle( debugger->process, event->data.info.create_process.process );
|
||||
close_handle( debugger->process, event->data.info.create_process.thread );
|
||||
return 0;
|
||||
}
|
||||
event->data.info.create_process.file = handle;
|
||||
event->data.info.create_process.teb = thread->teb;
|
||||
event->data.info.create_process.base = thread->process->module;
|
||||
event->data.info.create_process.start = thread->entry;
|
||||
event->data.info.create_process.dbg_offset = 0;
|
||||
event->data.info.create_process.dbg_size = 0;
|
||||
event->data.info.create_process.name = 0;
|
||||
event->data.info.create_process.unicode = 0;
|
||||
break;
|
||||
case LOAD_DLL_DEBUG_EVENT:
|
||||
if ((handle = event->data.info.load_dll.handle) != -1)
|
||||
|
@ -131,6 +144,15 @@ static int fill_debug_event( struct thread *debugger, struct thread *thread,
|
|||
event->data.info.load_dll.handle = handle;
|
||||
}
|
||||
break;
|
||||
case EXIT_PROCESS_DEBUG_EVENT:
|
||||
case EXIT_THREAD_DEBUG_EVENT:
|
||||
event->data.info.exit.exit_code = thread->exit_code;
|
||||
break;
|
||||
case EXCEPTION_DEBUG_EVENT:
|
||||
case UNLOAD_DLL_DEBUG_EVENT:
|
||||
case OUTPUT_DEBUG_STRING_EVENT:
|
||||
case RIP_EVENT:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -189,7 +211,6 @@ static void build_wait_debug_reply( struct thread *thread, struct object *obj, i
|
|||
req->event.code = 0;
|
||||
req->pid = 0;
|
||||
req->tid = 0;
|
||||
thread->error = signaled;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,9 +351,10 @@ static int continue_debug_event( struct process *process, struct thread *thread,
|
|||
}
|
||||
|
||||
/* queue a debug event for a debugger */
|
||||
static struct debug_event *queue_debug_event( struct thread *debugger, struct thread *thread,
|
||||
static struct debug_event *queue_debug_event( struct thread *thread, int code,
|
||||
debug_event_t *data )
|
||||
{
|
||||
struct thread *debugger = thread->process->debugger;
|
||||
struct debug_ctx *debug_ctx = debugger->debug_ctx;
|
||||
struct debug_event *event;
|
||||
|
||||
|
@ -347,7 +369,8 @@ static struct debug_event *queue_debug_event( struct thread *debugger, struct th
|
|||
event->state = EVENT_QUEUED;
|
||||
event->sender = (struct thread *)grab_object( thread );
|
||||
event->debugger = (struct thread *)grab_object( debugger );
|
||||
memcpy( &event->data, data, sizeof(event->data) );
|
||||
if (data) memcpy( &event->data, data, sizeof(event->data) );
|
||||
event->data.code = code;
|
||||
|
||||
if (!fill_debug_event( debugger, thread, event ))
|
||||
{
|
||||
|
@ -361,6 +384,16 @@ static struct debug_event *queue_debug_event( struct thread *debugger, struct th
|
|||
return event;
|
||||
}
|
||||
|
||||
/* generate a debug event from inside the server and queue it */
|
||||
void generate_debug_event( struct thread *thread, int code )
|
||||
{
|
||||
if (thread->process->debugger)
|
||||
{
|
||||
struct debug_event *event = queue_debug_event( thread, code, NULL );
|
||||
if (event) release_object( event );
|
||||
}
|
||||
}
|
||||
|
||||
/* return a pointer to the context in case the thread is inside an exception event */
|
||||
CONTEXT *get_debug_context( struct thread *thread )
|
||||
{
|
||||
|
@ -409,29 +442,14 @@ int debugger_attach( struct process *process, struct thread *debugger )
|
|||
}
|
||||
|
||||
/* a thread is exiting */
|
||||
void debug_exit_thread( struct thread *thread, int exit_code )
|
||||
void debug_exit_thread( struct thread *thread )
|
||||
{
|
||||
struct thread *debugger = thread->process->debugger;
|
||||
struct debug_ctx *debug_ctx = thread->debug_ctx;
|
||||
|
||||
if (debugger) /* being debugged -> send an event to the debugger */
|
||||
{
|
||||
struct debug_event *event;
|
||||
debug_event_t exit;
|
||||
exit.info.exit.exit_code = exit_code;
|
||||
/* if this is the last thread, send an exit process event */
|
||||
exit.code = ((thread->process->running_threads == 1) ?
|
||||
EXIT_PROCESS_DEBUG_EVENT : EXIT_THREAD_DEBUG_EVENT);
|
||||
event = queue_debug_event( debugger, thread, &exit );
|
||||
if (event) release_object( event );
|
||||
}
|
||||
|
||||
if (debug_ctx) /* this thread is a debugger */
|
||||
if (thread->debug_ctx) /* this thread is a debugger */
|
||||
{
|
||||
/* kill all debugged processes */
|
||||
kill_debugged_processes( thread, exit_code );
|
||||
kill_debugged_processes( thread, thread->exit_code );
|
||||
release_object( thread->debug_ctx );
|
||||
thread->debug_ctx = NULL;
|
||||
release_object( debug_ctx );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,27 +484,30 @@ DECL_HANDLER(continue_debug_event)
|
|||
DECL_HANDLER(debug_process)
|
||||
{
|
||||
struct process *process = get_process_from_id( req->pid );
|
||||
if (process)
|
||||
if (!process) return;
|
||||
if (debugger_attach( process, current ))
|
||||
{
|
||||
debugger_attach( process, current );
|
||||
/* FIXME: should notify the debugged process somehow */
|
||||
release_object( process );
|
||||
struct thread *thread = process->thread_list;
|
||||
generate_debug_event( thread, CREATE_PROCESS_DEBUG_EVENT );
|
||||
while ((thread = thread->next)) generate_debug_event( thread, CREATE_THREAD_DEBUG_EVENT );
|
||||
/* FIXME: load dll + breakpoint exception events */
|
||||
}
|
||||
release_object( process );
|
||||
}
|
||||
|
||||
/* Send a debug event */
|
||||
DECL_HANDLER(send_debug_event)
|
||||
{
|
||||
struct thread *debugger = current->process->debugger;
|
||||
struct debug_event *event;
|
||||
int code = req->event.code;
|
||||
|
||||
if ((req->event.code <= 0) || (req->event.code > RIP_EVENT))
|
||||
if ((code <= 0) || (code > RIP_EVENT))
|
||||
{
|
||||
fatal_protocol_error( current, "send_debug_event: bad code %d\n", req->event.code );
|
||||
fatal_protocol_error( current, "send_debug_event: bad code %d\n", code );
|
||||
return;
|
||||
}
|
||||
req->status = 0;
|
||||
if (debugger && ((event = queue_debug_event( debugger, current, &req->event ))))
|
||||
if (current->process->debugger && ((event = queue_debug_event( current, code, &req->event ))))
|
||||
{
|
||||
/* wait for continue_debug_event */
|
||||
struct object *obj = &event->obj;
|
||||
|
|
|
@ -154,7 +154,8 @@ extern int free_console( struct process *process );
|
|||
/* debugger functions */
|
||||
|
||||
extern int debugger_attach( struct process *process, struct thread *debugger );
|
||||
extern void debug_exit_thread( struct thread *thread, int exit_code );
|
||||
extern void generate_debug_event( struct thread *thread, int code );
|
||||
extern void debug_exit_thread( struct thread *thread );
|
||||
extern CONTEXT *get_debug_context( struct thread *thread );
|
||||
|
||||
/* mapping functions */
|
||||
|
|
|
@ -584,6 +584,9 @@ DECL_HANDLER(init_process_done)
|
|||
fatal_protocol_error( current, "init_process_done: no event\n" );
|
||||
return;
|
||||
}
|
||||
current->entry = req->entry;
|
||||
process->module = req->module;
|
||||
generate_debug_event( current, CREATE_PROCESS_DEBUG_EVENT );
|
||||
set_event( process->init_event );
|
||||
release_object( process->init_event );
|
||||
process->init_event = NULL;
|
||||
|
|
|
@ -37,6 +37,7 @@ struct process
|
|||
struct event *init_event; /* event for init done */
|
||||
void *ldt_copy; /* pointer to LDT copy in client addr space */
|
||||
void *ldt_flags; /* pointer to LDT flags in client addr space */
|
||||
void *module; /* main module base address */
|
||||
struct new_process_request *info; /* startup info (freed after startup) */
|
||||
};
|
||||
|
||||
|
@ -66,4 +67,6 @@ 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 );
|
||||
|
||||
static inline void *get_process_id( struct process *process ) { return process; }
|
||||
|
||||
#endif /* __WINE_SERVER_PROCESS_H */
|
||||
|
|
|
@ -92,25 +92,32 @@ static struct thread *booting_thread;
|
|||
/* allocate the buffer for the communication with the client */
|
||||
static int alloc_client_buffer( struct thread *thread )
|
||||
{
|
||||
struct get_thread_buffer_request *req;
|
||||
int fd;
|
||||
|
||||
if ((fd = create_anonymous_file()) == -1) return -1;
|
||||
if (ftruncate( fd, MAX_REQUEST_LENGTH ) == -1) goto error;
|
||||
if ((thread->buffer = mmap( 0, MAX_REQUEST_LENGTH, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, 0 )) == (void*)-1) goto error;
|
||||
return fd;
|
||||
/* build the first request into the buffer and send it */
|
||||
req = thread->buffer;
|
||||
req->pid = get_process_id( thread->process );
|
||||
req->tid = get_thread_id( thread );
|
||||
req->boot = (thread == booting_thread);
|
||||
set_reply_fd( thread, fd );
|
||||
send_reply( thread );
|
||||
return 1;
|
||||
|
||||
error:
|
||||
file_set_error();
|
||||
if (fd != -1) close( fd );
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create a new thread */
|
||||
struct thread *create_thread( int fd, struct process *process, int suspend )
|
||||
{
|
||||
struct thread *thread;
|
||||
int buf_fd;
|
||||
|
||||
int flags = fcntl( fd, F_GETFL, 0 );
|
||||
fcntl( fd, F_SETFL, flags | O_NONBLOCK );
|
||||
|
@ -150,11 +157,8 @@ struct thread *create_thread( int fd, struct process *process, int suspend )
|
|||
first_thread = thread;
|
||||
add_process_thread( process, thread );
|
||||
|
||||
if ((buf_fd = alloc_client_buffer( thread )) == -1) goto error;
|
||||
|
||||
set_select_events( &thread->obj, POLLIN ); /* start listening to events */
|
||||
set_reply_fd( thread, buf_fd ); /* send the fd to the client */
|
||||
send_reply( thread );
|
||||
if (!alloc_client_buffer( thread )) goto error;
|
||||
return thread;
|
||||
|
||||
error:
|
||||
|
@ -560,7 +564,9 @@ void kill_thread( struct thread *thread, int exit_code )
|
|||
if (current == thread) current = NULL;
|
||||
if (debug_level) trace_kill( thread );
|
||||
if (thread->wait) end_wait( thread );
|
||||
debug_exit_thread( thread, exit_code );
|
||||
generate_debug_event( thread, (thread->process->running_threads == 1) ?
|
||||
EXIT_PROCESS_DEBUG_EVENT : EXIT_THREAD_DEBUG_EVENT );
|
||||
debug_exit_thread( thread );
|
||||
abandon_mutexes( thread );
|
||||
remove_process_thread( thread->process, thread );
|
||||
wake_up( &thread->obj, 0 );
|
||||
|
@ -623,10 +629,10 @@ DECL_HANDLER(init_thread)
|
|||
}
|
||||
current->unix_pid = req->unix_pid;
|
||||
current->teb = req->teb;
|
||||
current->entry = req->entry;
|
||||
if (current->suspend + current->process->suspend > 0) stop_thread( current );
|
||||
req->pid = current->process;
|
||||
req->tid = current;
|
||||
req->boot = (current == booting_thread);
|
||||
if (current->process->running_threads > 1)
|
||||
generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT );
|
||||
}
|
||||
|
||||
/* terminate a thread */
|
||||
|
|
|
@ -48,6 +48,7 @@ struct thread
|
|||
int exit_code; /* thread exit code */
|
||||
int unix_pid; /* Unix pid of client */
|
||||
void *teb; /* TEB address (in client address space) */
|
||||
void *entry; /* thread entry point (in client address space) */
|
||||
int priority; /* priority level */
|
||||
int affinity; /* affinity mask */
|
||||
int suspend; /* suspend count */
|
||||
|
@ -92,4 +93,6 @@ static inline int get_error(void) { return current->error; }
|
|||
static inline void set_error( int err ) { current->error = err; }
|
||||
static inline void clear_error(void) { set_error(0); }
|
||||
|
||||
static inline void *get_thread_id( struct thread *thread ) { return thread; }
|
||||
|
||||
#endif /* __WINE_SERVER_THREAD_H */
|
||||
|
|
|
@ -258,25 +258,26 @@ static void dump_init_process_reply( const struct init_process_request *req )
|
|||
|
||||
static void dump_init_process_done_request( const struct init_process_done_request *req )
|
||||
{
|
||||
fprintf( stderr, " dummy=%d", req->dummy );
|
||||
fprintf( stderr, " module=%p,", req->module );
|
||||
fprintf( stderr, " entry=%p", req->entry );
|
||||
}
|
||||
|
||||
static void dump_init_thread_request( const struct init_thread_request *req )
|
||||
{
|
||||
fprintf( stderr, " unix_pid=%d,", req->unix_pid );
|
||||
fprintf( stderr, " teb=%p", req->teb );
|
||||
}
|
||||
|
||||
static void dump_init_thread_reply( const struct init_thread_request *req )
|
||||
{
|
||||
fprintf( stderr, " pid=%p,", req->pid );
|
||||
fprintf( stderr, " tid=%p,", req->tid );
|
||||
fprintf( stderr, " boot=%d", req->boot );
|
||||
fprintf( stderr, " teb=%p,", req->teb );
|
||||
fprintf( stderr, " entry=%p", req->entry );
|
||||
}
|
||||
|
||||
static void dump_get_thread_buffer_request( const struct get_thread_buffer_request *req )
|
||||
{
|
||||
fprintf( stderr, " dummy=%d", req->dummy );
|
||||
}
|
||||
|
||||
static void dump_get_thread_buffer_reply( const struct get_thread_buffer_request *req )
|
||||
{
|
||||
fprintf( stderr, " pid=%p,", req->pid );
|
||||
fprintf( stderr, " tid=%p,", req->tid );
|
||||
fprintf( stderr, " boot=%d", req->boot );
|
||||
}
|
||||
|
||||
static void dump_terminate_process_request( const struct terminate_process_request *req )
|
||||
|
@ -1329,8 +1330,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)0,
|
||||
(dump_func)dump_init_process_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_init_thread_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_thread_buffer_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_process_info_reply,
|
||||
|
|
Loading…
Reference in New Issue