Generate CREATE_PROCESS/THREAD debug events internally in the server.

oldstable
Alexandre Julliard 2000-03-08 12:01:30 +00:00
parent ca3c9ba4ec
commit ff81d78708
13 changed files with 135 additions and 153 deletions

View File

@ -170,8 +170,6 @@ extern void PROCESS_WalkProcess( void );
/* scheduler/debugger.c */ /* scheduler/debugger.c */
extern DWORD DEBUG_SendExceptionEvent( EXCEPTION_RECORD *rec, BOOL first_chance, CONTEXT *ctx ); 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_SendLoadDLLEvent( HFILE file, HMODULE module, LPSTR *name );
extern DWORD DEBUG_SendUnloadDLLEvent( HMODULE module ); extern DWORD DEBUG_SendUnloadDLLEvent( HMODULE module );

View File

@ -165,7 +165,8 @@ struct init_process_request
/* Signal the end of the process initialization */ /* Signal the end of the process initialization */
struct init_process_done_request 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 int unix_pid; /* Unix pid of new thread */
IN void* teb; /* TEB of new thread (in thread address space) */ IN void* teb; /* TEB of new thread (in thread address space) */
OUT void* pid; /* process id of the new thread's process */ IN void* entry; /* thread entry point (in thread address space) */
OUT void* tid; /* thread id of the new thread */
OUT int boot; /* is this the boot thread? */
}; };
@ -185,7 +184,9 @@ struct init_thread_request
/* created thread gets (without having to request it) */ /* created thread gets (without having to request it) */
struct get_thread_buffer_request 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? */
}; };

View File

@ -453,6 +453,7 @@ int CLIENT_InitServer(void)
*/ */
int CLIENT_InitThread(void) int CLIENT_InitThread(void)
{ {
struct get_thread_buffer_request *first_req;
struct init_thread_request *req; struct init_thread_request *req;
TEB *teb = NtCurrentTeb(); TEB *teb = NtCurrentTeb();
int fd; 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 ); teb->buffer = mmap( 0, teb->buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
close( fd ); close( fd );
if (teb->buffer == (void*)-1) server_perror( "mmap" ); 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->unix_pid = getpid();
req->teb = teb; req->teb = teb;
if (server_call( REQ_INIT_THREAD )) return -1; req->entry = teb->entry_point;
teb->process->server_pid = req->pid; return server_call_noerr( REQ_INIT_THREAD );
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;
} }
/*********************************************************************** /***********************************************************************

View File

@ -6,8 +6,8 @@
#include <string.h> #include <string.h>
#include "winerror.h"
#include "process.h" #include "process.h"
#include "thread.h"
#include "server.h" #include "server.h"
#include "debugtools.h" #include "debugtools.h"
@ -22,7 +22,6 @@ DEFAULT_DEBUG_CHANNEL(debugstr);
DWORD DEBUG_SendExceptionEvent( EXCEPTION_RECORD *rec, BOOL first_chance, CONTEXT *context ) DWORD DEBUG_SendExceptionEvent( EXCEPTION_RECORD *rec, BOOL first_chance, CONTEXT *context )
{ {
int i; int i;
DWORD ret = 0;
struct send_debug_event_request *req = get_req_buffer(); struct send_debug_event_request *req = get_req_buffer();
req->event.code = EXCEPTION_DEBUG_EVENT; 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; req->event.info.exception.context = *context;
for (i = 0; i < req->event.info.exception.nb_params; i++) for (i = 0; i < req->event.info.exception.nb_params; i++)
req->event.info.exception.params[i] = rec->ExceptionInformation[i]; req->event.info.exception.params[i] = rec->ExceptionInformation[i];
if (!server_call( REQ_SEND_DEBUG_EVENT )) if (!server_call_noerr( REQ_SEND_DEBUG_EVENT ))
{
ret = req->status;
*context = req->event.info.exception.context; *context = req->event.info.exception.context;
} return req->status;
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;
} }
@ -97,7 +47,6 @@ DWORD DEBUG_SendCreateThreadEvent( void *entry )
*/ */
DWORD DEBUG_SendLoadDLLEvent( HFILE file, HMODULE module, LPSTR *name ) DWORD DEBUG_SendLoadDLLEvent( HFILE file, HMODULE module, LPSTR *name )
{ {
DWORD ret = 0;
struct send_debug_event_request *req = get_req_buffer(); struct send_debug_event_request *req = get_req_buffer();
req->event.code = LOAD_DLL_DEBUG_EVENT; 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.dbg_size = 0; /* FIXME */
req->event.info.load_dll.name = name; req->event.info.load_dll.name = name;
req->event.info.load_dll.unicode = 0; req->event.info.load_dll.unicode = 0;
if (!server_call( REQ_SEND_DEBUG_EVENT )) ret = req->status; server_call_noerr( REQ_SEND_DEBUG_EVENT );
return ret; return req->status;
} }
@ -119,13 +68,12 @@ DWORD DEBUG_SendLoadDLLEvent( HFILE file, HMODULE module, LPSTR *name )
*/ */
DWORD DEBUG_SendUnloadDLLEvent( HMODULE module ) DWORD DEBUG_SendUnloadDLLEvent( HMODULE module )
{ {
DWORD ret = 0;
struct send_debug_event_request *req = get_req_buffer(); struct send_debug_event_request *req = get_req_buffer();
req->event.code = UNLOAD_DLL_DEBUG_EVENT; req->event.code = UNLOAD_DLL_DEBUG_EVENT;
req->event.info.unload_dll.base = (void *)module; req->event.info.unload_dll.base = (void *)module;
if (!server_call( REQ_SEND_DEBUG_EVENT )) ret = req->status; server_call_noerr( REQ_SEND_DEBUG_EVENT );
return ret; return req->status;
} }
@ -155,6 +103,9 @@ BOOL WINAPI WaitForDebugEvent( LPDEBUG_EVENT event, DWORD timeout )
event->dwThreadId = (DWORD)req->tid; event->dwThreadId = (DWORD)req->tid;
switch(req->event.code) switch(req->event.code)
{ {
case 0: /* timeout */
SetLastError( ERROR_SEM_TIMEOUT );
return FALSE;
case EXCEPTION_DEBUG_EVENT: case EXCEPTION_DEBUG_EVENT:
event->u.Exception.ExceptionRecord.ExceptionCode = req->event.info.exception.code; event->u.Exception.ExceptionRecord.ExceptionCode = req->event.info.exception.code;
event->u.Exception.ExceptionRecord.ExceptionFlags = req->event.info.exception.flags; event->u.Exception.ExceptionRecord.ExceptionFlags = req->event.info.exception.flags;

View File

@ -26,7 +26,6 @@
#include "server.h" #include "server.h"
#include "options.h" #include "options.h"
#include "callback.h" #include "callback.h"
#include "debugger.h"
#include "debugtools.h" #include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(process) DEFAULT_DEBUG_CHANNEL(process)
@ -371,6 +370,7 @@ BOOL PROCESS_Init( BOOL win32 )
*/ */
void PROCESS_Start(void) void PROCESS_Start(void)
{ {
struct init_process_done_request *req = get_req_buffer();
UINT cmdShow = SW_SHOWNORMAL; UINT cmdShow = SW_SHOWNORMAL;
LPTHREAD_START_ROUTINE entry = NULL; LPTHREAD_START_ROUTINE entry = NULL;
PDB *pdb = PROCESS_Current(); PDB *pdb = PROCESS_Current();
@ -452,16 +452,15 @@ void PROCESS_Start(void)
PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0, 0 ); PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0, 0 );
/* Signal the parent process to continue */ /* Signal the parent process to continue */
req->module = (void *)pModule->module32;
req->entry = entry;
server_call( REQ_INIT_PROCESS_DONE ); server_call( REQ_INIT_PROCESS_DONE );
/* Send all required start-up debugger events */ /* Send all required start-up debugger events */
if ( type == PROC_WIN32 && (pdb->flags & PDB32_DEBUGGED) ) if ( type == PROC_WIN32 && (pdb->flags & PDB32_DEBUGGED) )
{ {
EnterCriticalSection( &pdb->crit_section ); EnterCriticalSection( &pdb->crit_section );
DEBUG_SendCreateProcessEvent( -1 /*FIXME*/, pModule->module32, entry );
MODULE_SendLoadDLLEvents(); MODULE_SendLoadDLLEvents();
LeaveCriticalSection( &pdb->crit_section ); LeaveCriticalSection( &pdb->crit_section );
} }
@ -479,10 +478,6 @@ void PROCESS_Start(void)
LeaveCriticalSection( &pdb->crit_section ); 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 */ /* Call UserSignalProc ( USIG_PROCESS_RUNNING ... ) only for non-GUI win32 apps */
if ( type != PROC_WIN16 && (pdb->flags & PDB32_CONSOLE_PROC)) if ( type != PROC_WIN16 && (pdb->flags & PDB32_CONSOLE_PROC))
PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0, 0 ); PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0, 0 );

View File

@ -276,9 +276,6 @@ static void THREAD_Start(void)
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, (DWORD)NtCurrentTeb()->tid, 0 ); PROCESS_CallUserSignalProc( USIG_THREAD_INIT, (DWORD)NtCurrentTeb()->tid, 0 );
PE_InitTls(); PE_InitTls();
MODULE_DllThreadAttach( NULL ); MODULE_DllThreadAttach( NULL );
if (NtCurrentTeb()->process->flags & PDB32_DEBUGGED) DEBUG_SendCreateThreadEvent( func );
ExitThread( func( NtCurrentTeb()->entry_arg ) ); ExitThread( func( NtCurrentTeb()->entry_arg ) );
} }

View File

@ -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 */ /* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
THREAD_ALL_ACCESS, FALSE )) == -1) THREAD_ALL_ACCESS, FALSE )) == -1)
return 0; return 0;
event->data.info.create_thread.teb = thread->teb;
event->data.info.create_thread.start = thread->entry;
break; break;
case CREATE_PROCESS_DEBUG_EVENT: case CREATE_PROCESS_DEBUG_EVENT:
if ((handle = event->data.info.create_process.file) != -1) if ((handle = alloc_handle( debugger->process, thread->process,
{ /* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
if ((handle = duplicate_handle( thread->process, handle, debugger->process, PROCESS_ALL_ACCESS, FALSE )) == -1)
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 );
return 0; return 0;
} event->data.info.create_process.process = handle;
if ((event->data.info.create_process.thread = alloc_handle( debugger->process, thread,
if ((handle = alloc_handle( debugger->process, thread,
/* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */ /* 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 ); close_handle( debugger->process, event->data.info.create_process.process );
return 0; 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; break;
case LOAD_DLL_DEBUG_EVENT: case LOAD_DLL_DEBUG_EVENT:
if ((handle = event->data.info.load_dll.handle) != -1) 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; event->data.info.load_dll.handle = handle;
} }
break; 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; return 1;
} }
@ -189,7 +211,6 @@ static void build_wait_debug_reply( struct thread *thread, struct object *obj, i
req->event.code = 0; req->event.code = 0;
req->pid = 0; req->pid = 0;
req->tid = 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 */ /* 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 ) debug_event_t *data )
{ {
struct thread *debugger = thread->process->debugger;
struct debug_ctx *debug_ctx = debugger->debug_ctx; struct debug_ctx *debug_ctx = debugger->debug_ctx;
struct debug_event *event; 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->state = EVENT_QUEUED;
event->sender = (struct thread *)grab_object( thread ); event->sender = (struct thread *)grab_object( thread );
event->debugger = (struct thread *)grab_object( debugger ); 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 )) 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; 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 */ /* return a pointer to the context in case the thread is inside an exception event */
CONTEXT *get_debug_context( struct thread *thread ) CONTEXT *get_debug_context( struct thread *thread )
{ {
@ -409,29 +442,14 @@ int debugger_attach( struct process *process, struct thread *debugger )
} }
/* a thread is exiting */ /* 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; if (thread->debug_ctx) /* this thread is a 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 */
{ {
/* kill all debugged processes */ /* 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; thread->debug_ctx = NULL;
release_object( debug_ctx );
} }
} }
@ -466,27 +484,30 @@ DECL_HANDLER(continue_debug_event)
DECL_HANDLER(debug_process) DECL_HANDLER(debug_process)
{ {
struct process *process = get_process_from_id( req->pid ); struct process *process = get_process_from_id( req->pid );
if (process) if (!process) return;
if (debugger_attach( process, current ))
{ {
debugger_attach( process, current ); struct thread *thread = process->thread_list;
/* FIXME: should notify the debugged process somehow */ generate_debug_event( thread, CREATE_PROCESS_DEBUG_EVENT );
release_object( process ); 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 */ /* Send a debug event */
DECL_HANDLER(send_debug_event) DECL_HANDLER(send_debug_event)
{ {
struct thread *debugger = current->process->debugger;
struct debug_event *event; 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; return;
} }
req->status = 0; 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 */ /* wait for continue_debug_event */
struct object *obj = &event->obj; struct object *obj = &event->obj;

View File

@ -154,7 +154,8 @@ extern int free_console( struct process *process );
/* debugger functions */ /* debugger functions */
extern int debugger_attach( struct process *process, struct thread *debugger ); 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 ); extern CONTEXT *get_debug_context( struct thread *thread );
/* mapping functions */ /* mapping functions */

View File

@ -584,6 +584,9 @@ DECL_HANDLER(init_process_done)
fatal_protocol_error( current, "init_process_done: no event\n" ); fatal_protocol_error( current, "init_process_done: no event\n" );
return; return;
} }
current->entry = req->entry;
process->module = req->module;
generate_debug_event( current, CREATE_PROCESS_DEBUG_EVENT );
set_event( process->init_event ); set_event( process->init_event );
release_object( process->init_event ); release_object( process->init_event );
process->init_event = NULL; process->init_event = NULL;

View File

@ -37,6 +37,7 @@ struct process
struct event *init_event; /* event for init done */ struct event *init_event; /* event for init done */
void *ldt_copy; /* pointer to LDT copy in client addr space */ void *ldt_copy; /* pointer to LDT copy in client addr space */
void *ldt_flags; /* pointer to LDT flags 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) */ 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 void kill_debugged_processes( struct thread *debugger, int exit_code );
extern struct process_snapshot *process_snap( int *count ); extern struct process_snapshot *process_snap( int *count );
static inline void *get_process_id( struct process *process ) { return process; }
#endif /* __WINE_SERVER_PROCESS_H */ #endif /* __WINE_SERVER_PROCESS_H */

View File

@ -92,25 +92,32 @@ static struct thread *booting_thread;
/* allocate the buffer for the communication with the client */ /* allocate the buffer for the communication with the client */
static int alloc_client_buffer( struct thread *thread ) static int alloc_client_buffer( struct thread *thread )
{ {
struct get_thread_buffer_request *req;
int fd; int fd;
if ((fd = create_anonymous_file()) == -1) return -1; if ((fd = create_anonymous_file()) == -1) return -1;
if (ftruncate( fd, MAX_REQUEST_LENGTH ) == -1) goto error; if (ftruncate( fd, MAX_REQUEST_LENGTH ) == -1) goto error;
if ((thread->buffer = mmap( 0, MAX_REQUEST_LENGTH, PROT_READ | PROT_WRITE, if ((thread->buffer = mmap( 0, MAX_REQUEST_LENGTH, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0 )) == (void*)-1) goto error; 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: error:
file_set_error(); file_set_error();
if (fd != -1) close( fd ); if (fd != -1) close( fd );
return -1; return 0;
} }
/* create a new thread */ /* create a new thread */
struct thread *create_thread( int fd, struct process *process, int suspend ) struct thread *create_thread( int fd, struct process *process, int suspend )
{ {
struct thread *thread; struct thread *thread;
int buf_fd;
int flags = fcntl( fd, F_GETFL, 0 ); int flags = fcntl( fd, F_GETFL, 0 );
fcntl( fd, F_SETFL, flags | O_NONBLOCK ); 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; first_thread = thread;
add_process_thread( process, 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_select_events( &thread->obj, POLLIN ); /* start listening to events */
set_reply_fd( thread, buf_fd ); /* send the fd to the client */ if (!alloc_client_buffer( thread )) goto error;
send_reply( thread );
return thread; return thread;
error: error:
@ -560,7 +564,9 @@ void kill_thread( struct thread *thread, int exit_code )
if (current == thread) current = NULL; if (current == thread) current = NULL;
if (debug_level) trace_kill( thread ); if (debug_level) trace_kill( thread );
if (thread->wait) end_wait( 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 ); abandon_mutexes( thread );
remove_process_thread( thread->process, thread ); remove_process_thread( thread->process, thread );
wake_up( &thread->obj, 0 ); wake_up( &thread->obj, 0 );
@ -623,10 +629,10 @@ DECL_HANDLER(init_thread)
} }
current->unix_pid = req->unix_pid; current->unix_pid = req->unix_pid;
current->teb = req->teb; current->teb = req->teb;
current->entry = req->entry;
if (current->suspend + current->process->suspend > 0) stop_thread( current ); if (current->suspend + current->process->suspend > 0) stop_thread( current );
req->pid = current->process; if (current->process->running_threads > 1)
req->tid = current; generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT );
req->boot = (current == booting_thread);
} }
/* terminate a thread */ /* terminate a thread */

View File

@ -48,6 +48,7 @@ struct thread
int exit_code; /* thread exit code */ int exit_code; /* thread exit code */
int unix_pid; /* Unix pid of client */ int unix_pid; /* Unix pid of client */
void *teb; /* TEB address (in client address space) */ void *teb; /* TEB address (in client address space) */
void *entry; /* thread entry point (in client address space) */
int priority; /* priority level */ int priority; /* priority level */
int affinity; /* affinity mask */ int affinity; /* affinity mask */
int suspend; /* suspend count */ 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 set_error( int err ) { current->error = err; }
static inline void clear_error(void) { set_error(0); } 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 */ #endif /* __WINE_SERVER_THREAD_H */

View File

@ -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 ) 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 ) static void dump_init_thread_request( const struct init_thread_request *req )
{ {
fprintf( stderr, " unix_pid=%d,", req->unix_pid ); fprintf( stderr, " unix_pid=%d,", req->unix_pid );
fprintf( stderr, " teb=%p", req->teb ); fprintf( stderr, " teb=%p,", req->teb );
} fprintf( stderr, " entry=%p", req->entry );
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 );
} }
static void dump_get_thread_buffer_request( const struct get_thread_buffer_request *req ) 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 ) 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)0,
(dump_func)dump_init_process_reply, (dump_func)dump_init_process_reply,
(dump_func)0, (dump_func)0,
(dump_func)dump_init_thread_reply,
(dump_func)0, (dump_func)0,
(dump_func)dump_get_thread_buffer_reply,
(dump_func)0, (dump_func)0,
(dump_func)0, (dump_func)0,
(dump_func)dump_get_process_info_reply, (dump_func)dump_get_process_info_reply,