mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-01 18:58:29 +00:00
server: Store a debug object instead of a debugger thread in the process.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
aec961e529
commit
faa9f5be59
|
@ -347,6 +347,8 @@ static void debug_obj_destroy( struct object *obj )
|
|||
struct debug_obj *debug_obj = (struct debug_obj *)obj;
|
||||
assert( obj->ops == &debug_obj_ops );
|
||||
|
||||
detach_debugged_processes( debug_obj, debug_obj->kill_on_exit ? STATUS_DEBUGGER_INACTIVE : 0 );
|
||||
|
||||
/* free all pending events */
|
||||
while ((ptr = list_head( &debug_obj->event_queue )))
|
||||
unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry ));
|
||||
|
@ -373,7 +375,7 @@ static int continue_debug_event( struct process *process, struct thread *thread,
|
|||
{
|
||||
struct debug_obj *debug_obj = current->debug_obj;
|
||||
|
||||
if (debug_obj && process->debugger == current && thread->process == process)
|
||||
if (debug_obj && process->debug_obj == debug_obj && thread->process == process)
|
||||
{
|
||||
struct debug_event *event;
|
||||
|
||||
|
@ -424,12 +426,9 @@ static int continue_debug_event( struct process *process, struct thread *thread,
|
|||
/* alloc a debug event for a debugger */
|
||||
static struct debug_event *alloc_debug_event( struct thread *thread, int code, const void *arg )
|
||||
{
|
||||
struct thread *debugger = thread->process->debugger;
|
||||
struct debug_event *event;
|
||||
|
||||
assert( code > 0 && code <= NB_DEBUG_EVENTS );
|
||||
/* cannot queue a debug event for myself */
|
||||
assert( debugger->process != thread->process );
|
||||
|
||||
/* build the event */
|
||||
if (!(event = alloc_object( &debug_event_ops ))) return NULL;
|
||||
|
@ -446,9 +445,10 @@ static struct debug_event *alloc_debug_event( struct thread *thread, int code, c
|
|||
/* generate a debug event from inside the server and queue it */
|
||||
void generate_debug_event( struct thread *thread, int code, const void *arg )
|
||||
{
|
||||
if (thread->process->debugger)
|
||||
struct debug_obj *debug_obj = thread->process->debug_obj;
|
||||
|
||||
if (debug_obj)
|
||||
{
|
||||
struct debug_obj *debug_obj = thread->process->debugger->debug_obj;
|
||||
struct debug_event *event = alloc_debug_event( thread, code, arg );
|
||||
if (event)
|
||||
{
|
||||
|
@ -462,17 +462,16 @@ void generate_debug_event( struct thread *thread, int code, const void *arg )
|
|||
|
||||
void resume_delayed_debug_events( struct thread *thread )
|
||||
{
|
||||
struct thread *debugger = thread->process->debugger;
|
||||
struct debug_obj *debug_obj = thread->process->debug_obj;
|
||||
struct debug_event *event;
|
||||
|
||||
if (debugger)
|
||||
if (debug_obj)
|
||||
{
|
||||
assert( debugger->debug_obj );
|
||||
LIST_FOR_EACH_ENTRY( event, &debugger->debug_obj->event_queue, struct debug_event, entry )
|
||||
LIST_FOR_EACH_ENTRY( event, &debug_obj->event_queue, struct debug_event, entry )
|
||||
{
|
||||
if (event->sender != thread) continue;
|
||||
if (event->state != EVENT_DELAYED) continue;
|
||||
resume_event( debugger->debug_obj, event );
|
||||
resume_event( debug_obj, event );
|
||||
suspend_process( thread->process );
|
||||
}
|
||||
}
|
||||
|
@ -481,7 +480,7 @@ void resume_delayed_debug_events( struct thread *thread )
|
|||
/* attach a process to a debugger thread and suspend it */
|
||||
static int debugger_attach( struct process *process, struct thread *debugger )
|
||||
{
|
||||
if (process->debugger) goto error; /* already being debugged */
|
||||
if (process->debug_obj) goto error; /* already being debugged */
|
||||
if (debugger->process == process) goto error;
|
||||
if (!is_process_init_done( process )) goto error; /* still starting up */
|
||||
if (list_empty( &process->thread_list )) goto error; /* no thread running in the process */
|
||||
|
@ -502,7 +501,7 @@ static int debugger_attach( struct process *process, struct thread *debugger )
|
|||
}
|
||||
if (!set_process_debug_flag( process, 1 ))
|
||||
{
|
||||
process->debugger = NULL;
|
||||
process->debug_obj = NULL;
|
||||
resume_process( process );
|
||||
return 0;
|
||||
}
|
||||
|
@ -515,23 +514,17 @@ static int debugger_attach( struct process *process, struct thread *debugger )
|
|||
}
|
||||
|
||||
|
||||
/* detach a process from a debugger thread (and resume it ?) */
|
||||
int debugger_detach( struct process *process, struct thread *debugger )
|
||||
/* detach a process from a debugger thread (and resume it) */
|
||||
void debugger_detach( struct process *process, struct debug_obj *debug_obj )
|
||||
{
|
||||
struct debug_event *event, *next;
|
||||
struct debug_obj *debug_obj;
|
||||
|
||||
if (!process->debugger || process->debugger != debugger)
|
||||
goto error; /* not currently debugged, or debugged by another debugger */
|
||||
if (!debugger->debug_obj ) goto error; /* should be a debugger */
|
||||
/* init should be done, otherwise wouldn't be attached */
|
||||
assert(is_process_init_done(process));
|
||||
|
||||
suspend_process( process );
|
||||
/* send continue indication for all events */
|
||||
debug_obj = debugger->debug_obj;
|
||||
|
||||
/* free all events from this process */
|
||||
/* send continue indication for all events */
|
||||
LIST_FOR_EACH_ENTRY_SAFE( event, next, &debug_obj->event_queue, struct debug_event, entry )
|
||||
{
|
||||
if (event->sender->process != process) continue;
|
||||
|
@ -546,16 +539,11 @@ int debugger_detach( struct process *process, struct thread *debugger )
|
|||
}
|
||||
|
||||
/* remove relationships between process and its debugger */
|
||||
process->debugger = NULL;
|
||||
process->debug_obj = NULL;
|
||||
if (!set_process_debug_flag( process, 0 )) clear_error(); /* ignore error */
|
||||
|
||||
/* from this function */
|
||||
resume_process( process );
|
||||
return 0;
|
||||
|
||||
error:
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* generate all startup events of a given process */
|
||||
|
@ -594,7 +582,7 @@ int set_process_debugger( struct process *process, struct thread *debugger )
|
|||
{
|
||||
struct debug_obj *debug_obj;
|
||||
|
||||
assert( !process->debugger );
|
||||
assert( !process->debug_obj );
|
||||
|
||||
if (!debugger->debug_obj) /* need to allocate a context */
|
||||
{
|
||||
|
@ -603,24 +591,18 @@ int set_process_debugger( struct process *process, struct thread *debugger )
|
|||
list_init( &debug_obj->event_queue );
|
||||
debugger->debug_obj = debug_obj;
|
||||
}
|
||||
process->debugger = debugger;
|
||||
process->debug_obj = debugger->debug_obj;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* a thread is exiting */
|
||||
void debug_exit_thread( struct thread *thread )
|
||||
{
|
||||
if (thread->debug_obj) /* this thread is a debugger */
|
||||
struct debug_obj *debug_obj = thread->debug_obj;
|
||||
|
||||
if (debug_obj) /* this thread is a debugger */
|
||||
{
|
||||
if (thread->debug_obj->kill_on_exit)
|
||||
{
|
||||
/* kill all debugged processes */
|
||||
kill_debugged_processes( thread, STATUS_DEBUGGER_INACTIVE );
|
||||
}
|
||||
else
|
||||
{
|
||||
detach_debugged_processes( thread );
|
||||
}
|
||||
detach_debugged_processes( debug_obj, debug_obj->kill_on_exit ? STATUS_DEBUGGER_INACTIVE : 0 );
|
||||
release_object( thread->debug_obj );
|
||||
thread->debug_obj = NULL;
|
||||
}
|
||||
|
@ -712,7 +694,10 @@ DECL_HANDLER(debug_process)
|
|||
|
||||
if (!req->attach)
|
||||
{
|
||||
debugger_detach( process, current );
|
||||
if (current->debug_obj && process->debug_obj == current->debug_obj)
|
||||
debugger_detach( process, current->debug_obj );
|
||||
else
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
}
|
||||
else if (debugger_attach( process, current ))
|
||||
{
|
||||
|
@ -725,11 +710,12 @@ DECL_HANDLER(debug_process)
|
|||
/* queue an exception event */
|
||||
DECL_HANDLER(queue_exception_event)
|
||||
{
|
||||
struct debug_obj *debug_obj = current->process->debug_obj;
|
||||
|
||||
reply->handle = 0;
|
||||
if (current->process->debugger)
|
||||
if (debug_obj)
|
||||
{
|
||||
debug_event_t data;
|
||||
struct debug_obj *debug_obj = current->process->debugger->debug_obj;
|
||||
struct debug_event *event;
|
||||
struct thread *thread = current;
|
||||
|
||||
|
|
|
@ -514,7 +514,7 @@ struct process *create_process( int fd, struct process *parent, int inherit_all,
|
|||
goto error;
|
||||
}
|
||||
process->parent_id = 0;
|
||||
process->debugger = NULL;
|
||||
process->debug_obj = NULL;
|
||||
process->debug_event = NULL;
|
||||
process->handles = NULL;
|
||||
process->msg_fd = NULL;
|
||||
|
@ -1038,8 +1038,8 @@ void kill_process( struct process *process, int violent_death )
|
|||
}
|
||||
}
|
||||
|
||||
/* kill all processes being debugged by a given thread */
|
||||
void kill_debugged_processes( struct thread *debugger, int exit_code )
|
||||
/* detach all processes being debugged by a given thread */
|
||||
void detach_debugged_processes( struct debug_obj *debug_obj, int exit_code )
|
||||
{
|
||||
for (;;) /* restart from the beginning of the list every time */
|
||||
{
|
||||
|
@ -1049,26 +1049,15 @@ void kill_debugged_processes( struct thread *debugger, int exit_code )
|
|||
LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
|
||||
{
|
||||
if (!process->running_threads) continue;
|
||||
if (process->debugger == debugger) break;
|
||||
if (process->debug_obj == debug_obj) break;
|
||||
}
|
||||
if (&process->entry == &process_list) break; /* no process found */
|
||||
process->debugger = NULL;
|
||||
terminate_process( process, NULL, exit_code );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* detach a debugger from all its debuggees */
|
||||
void detach_debugged_processes( struct thread *debugger )
|
||||
{
|
||||
struct process *process;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
|
||||
{
|
||||
if (process->debugger == debugger && process->running_threads)
|
||||
if (exit_code)
|
||||
{
|
||||
debugger_detach( process, debugger );
|
||||
process->debug_obj = NULL;
|
||||
terminate_process( process, NULL, exit_code );
|
||||
}
|
||||
else debugger_detach( process, debug_obj );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1266,9 +1255,9 @@ DECL_HANDLER(new_process)
|
|||
set_process_debugger( process, current );
|
||||
process->debug_children = !(req->create_flags & DEBUG_ONLY_THIS_PROCESS);
|
||||
}
|
||||
else if (current->process->debugger && current->process->debug_children)
|
||||
else if (current->process->debug_children)
|
||||
{
|
||||
set_process_debugger( process, current->process->debugger );
|
||||
process->debug_obj = current->process->debug_obj;
|
||||
/* debug_children is set to 1 by default */
|
||||
}
|
||||
|
||||
|
@ -1382,7 +1371,7 @@ DECL_HANDLER(init_process_done)
|
|||
set_process_startup_state( process, STARTUP_DONE );
|
||||
|
||||
if (req->gui) process->idle_event = create_event( NULL, NULL, 0, 1, 0, NULL );
|
||||
if (process->debugger) set_process_debug_flag( process, 1 );
|
||||
if (process->debug_obj) set_process_debug_flag( process, 1 );
|
||||
reply->suspend = (current->suspend || process->suspend);
|
||||
}
|
||||
|
||||
|
@ -1431,7 +1420,7 @@ DECL_HANDLER(get_process_info)
|
|||
reply->start_time = process->start_time;
|
||||
reply->end_time = process->end_time;
|
||||
reply->cpu = process->cpu;
|
||||
reply->debugger_present = !!process->debugger;
|
||||
reply->debugger_present = !!process->debug_obj;
|
||||
reply->debug_children = process->debug_children;
|
||||
if (get_reply_max_size())
|
||||
{
|
||||
|
|
|
@ -56,7 +56,7 @@ struct process
|
|||
struct list entry; /* entry in system-wide process list */
|
||||
process_id_t parent_id; /* parent process id (at the time of creation) */
|
||||
struct list thread_list; /* thread list */
|
||||
struct thread *debugger; /* thread debugging this process */
|
||||
struct debug_obj *debug_obj; /* debug object debugging this process */
|
||||
struct debug_event *debug_event; /* debug event being sent to debugger */
|
||||
struct handle_table *handles; /* handle entries */
|
||||
struct fd *msg_fd; /* fd for sendmsg/recvmsg */
|
||||
|
@ -115,7 +115,7 @@ extern struct thread *get_process_first_thread( struct process *process );
|
|||
extern struct process *get_process_from_id( process_id_t id );
|
||||
extern struct process *get_process_from_handle( obj_handle_t handle, unsigned int access );
|
||||
extern int process_set_debugger( struct process *process, struct thread *thread );
|
||||
extern int debugger_detach( struct process* process, struct thread* debugger );
|
||||
extern void debugger_detach( struct process *process, struct debug_obj *debug_obj );
|
||||
extern int set_process_debug_flag( struct process *process, int flag );
|
||||
|
||||
extern void add_process_thread( struct process *process,
|
||||
|
@ -126,8 +126,7 @@ extern void suspend_process( struct process *process );
|
|||
extern void resume_process( struct process *process );
|
||||
extern void kill_process( struct process *process, int violent_death );
|
||||
extern void kill_console_processes( struct thread *renderer, int exit_code );
|
||||
extern void kill_debugged_processes( struct thread *debugger, int exit_code );
|
||||
extern void detach_debugged_processes( struct thread *debugger );
|
||||
extern void detach_debugged_processes( struct debug_obj *debug_obj, int exit_code );
|
||||
extern void enum_processes( int (*cb)(struct process*, void*), void *user);
|
||||
|
||||
/* console functions */
|
||||
|
|
Loading…
Reference in a new issue