Changed wait_process and wait_debug_event requests to never block;
waiting is always done through WaitForSingleObject().
This commit is contained in:
parent
819bff4d33
commit
e9936d96e1
|
@ -31,82 +31,92 @@ BOOL WINAPI WaitForDebugEvent(
|
||||||
DWORD timeout /* Number of milliseconds to wait for event. */)
|
DWORD timeout /* Number of milliseconds to wait for event. */)
|
||||||
{
|
{
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
SERVER_START_REQ
|
DWORD res;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
{
|
{
|
||||||
debug_event_t *data;
|
HANDLE wait = 0;
|
||||||
struct wait_debug_event_request *req = server_alloc_req( sizeof(*req), sizeof(*data) );
|
SERVER_START_REQ
|
||||||
|
|
||||||
req->timeout = timeout;
|
|
||||||
if (!(ret = !server_call( REQ_WAIT_DEBUG_EVENT ))) goto done;
|
|
||||||
|
|
||||||
if (!server_data_size(req)) /* timeout */
|
|
||||||
{
|
{
|
||||||
SetLastError( ERROR_SEM_TIMEOUT );
|
debug_event_t *data;
|
||||||
ret = FALSE;
|
struct wait_debug_event_request *req = server_alloc_req( sizeof(*req), sizeof(*data) );
|
||||||
goto done;
|
|
||||||
|
req->get_handle = (timeout != 0);
|
||||||
|
if (!(ret = !server_call( REQ_WAIT_DEBUG_EVENT ))) goto done;
|
||||||
|
|
||||||
|
if (!server_data_size(req)) /* timeout */
|
||||||
|
{
|
||||||
|
wait = req->wait;
|
||||||
|
ret = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
data = server_data_ptr(req);
|
||||||
|
event->dwDebugEventCode = data->code;
|
||||||
|
event->dwProcessId = (DWORD)req->pid;
|
||||||
|
event->dwThreadId = (DWORD)req->tid;
|
||||||
|
switch(data->code)
|
||||||
|
{
|
||||||
|
case EXCEPTION_DEBUG_EVENT:
|
||||||
|
event->u.Exception.ExceptionRecord = data->info.exception.record;
|
||||||
|
event->u.Exception.dwFirstChance = data->info.exception.first;
|
||||||
|
break;
|
||||||
|
case CREATE_THREAD_DEBUG_EVENT:
|
||||||
|
event->u.CreateThread.hThread = data->info.create_thread.handle;
|
||||||
|
event->u.CreateThread.lpThreadLocalBase = data->info.create_thread.teb;
|
||||||
|
event->u.CreateThread.lpStartAddress = data->info.create_thread.start;
|
||||||
|
break;
|
||||||
|
case CREATE_PROCESS_DEBUG_EVENT:
|
||||||
|
event->u.CreateProcessInfo.hFile = data->info.create_process.file;
|
||||||
|
event->u.CreateProcessInfo.hProcess = data->info.create_process.process;
|
||||||
|
event->u.CreateProcessInfo.hThread = data->info.create_process.thread;
|
||||||
|
event->u.CreateProcessInfo.lpBaseOfImage = data->info.create_process.base;
|
||||||
|
event->u.CreateProcessInfo.dwDebugInfoFileOffset = data->info.create_process.dbg_offset;
|
||||||
|
event->u.CreateProcessInfo.nDebugInfoSize = data->info.create_process.dbg_size;
|
||||||
|
event->u.CreateProcessInfo.lpThreadLocalBase = data->info.create_process.teb;
|
||||||
|
event->u.CreateProcessInfo.lpStartAddress = data->info.create_process.start;
|
||||||
|
event->u.CreateProcessInfo.lpImageName = data->info.create_process.name;
|
||||||
|
event->u.CreateProcessInfo.fUnicode = data->info.create_process.unicode;
|
||||||
|
if (data->info.create_process.file == -1) event->u.CreateProcessInfo.hFile = 0;
|
||||||
|
break;
|
||||||
|
case EXIT_THREAD_DEBUG_EVENT:
|
||||||
|
event->u.ExitThread.dwExitCode = data->info.exit.exit_code;
|
||||||
|
break;
|
||||||
|
case EXIT_PROCESS_DEBUG_EVENT:
|
||||||
|
event->u.ExitProcess.dwExitCode = data->info.exit.exit_code;
|
||||||
|
break;
|
||||||
|
case LOAD_DLL_DEBUG_EVENT:
|
||||||
|
event->u.LoadDll.hFile = data->info.load_dll.handle;
|
||||||
|
event->u.LoadDll.lpBaseOfDll = data->info.load_dll.base;
|
||||||
|
event->u.LoadDll.dwDebugInfoFileOffset = data->info.load_dll.dbg_offset;
|
||||||
|
event->u.LoadDll.nDebugInfoSize = data->info.load_dll.dbg_size;
|
||||||
|
event->u.LoadDll.lpImageName = data->info.load_dll.name;
|
||||||
|
event->u.LoadDll.fUnicode = data->info.load_dll.unicode;
|
||||||
|
if (data->info.load_dll.handle == -1) event->u.LoadDll.hFile = 0;
|
||||||
|
break;
|
||||||
|
case UNLOAD_DLL_DEBUG_EVENT:
|
||||||
|
event->u.UnloadDll.lpBaseOfDll = data->info.unload_dll.base;
|
||||||
|
break;
|
||||||
|
case OUTPUT_DEBUG_STRING_EVENT:
|
||||||
|
event->u.DebugString.lpDebugStringData = data->info.output_string.string;
|
||||||
|
event->u.DebugString.fUnicode = data->info.output_string.unicode;
|
||||||
|
event->u.DebugString.nDebugStringLength = data->info.output_string.length;
|
||||||
|
break;
|
||||||
|
case RIP_EVENT:
|
||||||
|
event->u.RipInfo.dwError = data->info.rip_info.error;
|
||||||
|
event->u.RipInfo.dwType = data->info.rip_info.type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
done:
|
||||||
}
|
}
|
||||||
data = server_data_ptr(req);
|
SERVER_END_REQ;
|
||||||
event->dwDebugEventCode = data->code;
|
if (ret) return TRUE;
|
||||||
event->dwProcessId = (DWORD)req->pid;
|
if (!wait) break;
|
||||||
event->dwThreadId = (DWORD)req->tid;
|
res = WaitForSingleObject( wait, timeout );
|
||||||
switch(data->code)
|
CloseHandle( wait );
|
||||||
{
|
if (res != STATUS_WAIT_0) break;
|
||||||
case EXCEPTION_DEBUG_EVENT:
|
|
||||||
event->u.Exception.ExceptionRecord = data->info.exception.record;
|
|
||||||
event->u.Exception.dwFirstChance = data->info.exception.first;
|
|
||||||
break;
|
|
||||||
case CREATE_THREAD_DEBUG_EVENT:
|
|
||||||
event->u.CreateThread.hThread = data->info.create_thread.handle;
|
|
||||||
event->u.CreateThread.lpThreadLocalBase = data->info.create_thread.teb;
|
|
||||||
event->u.CreateThread.lpStartAddress = data->info.create_thread.start;
|
|
||||||
break;
|
|
||||||
case CREATE_PROCESS_DEBUG_EVENT:
|
|
||||||
event->u.CreateProcessInfo.hFile = data->info.create_process.file;
|
|
||||||
event->u.CreateProcessInfo.hProcess = data->info.create_process.process;
|
|
||||||
event->u.CreateProcessInfo.hThread = data->info.create_process.thread;
|
|
||||||
event->u.CreateProcessInfo.lpBaseOfImage = data->info.create_process.base;
|
|
||||||
event->u.CreateProcessInfo.dwDebugInfoFileOffset = data->info.create_process.dbg_offset;
|
|
||||||
event->u.CreateProcessInfo.nDebugInfoSize = data->info.create_process.dbg_size;
|
|
||||||
event->u.CreateProcessInfo.lpThreadLocalBase = data->info.create_process.teb;
|
|
||||||
event->u.CreateProcessInfo.lpStartAddress = data->info.create_process.start;
|
|
||||||
event->u.CreateProcessInfo.lpImageName = data->info.create_process.name;
|
|
||||||
event->u.CreateProcessInfo.fUnicode = data->info.create_process.unicode;
|
|
||||||
if (data->info.create_process.file == -1) event->u.CreateProcessInfo.hFile = 0;
|
|
||||||
break;
|
|
||||||
case EXIT_THREAD_DEBUG_EVENT:
|
|
||||||
event->u.ExitThread.dwExitCode = data->info.exit.exit_code;
|
|
||||||
break;
|
|
||||||
case EXIT_PROCESS_DEBUG_EVENT:
|
|
||||||
event->u.ExitProcess.dwExitCode = data->info.exit.exit_code;
|
|
||||||
break;
|
|
||||||
case LOAD_DLL_DEBUG_EVENT:
|
|
||||||
event->u.LoadDll.hFile = data->info.load_dll.handle;
|
|
||||||
event->u.LoadDll.lpBaseOfDll = data->info.load_dll.base;
|
|
||||||
event->u.LoadDll.dwDebugInfoFileOffset = data->info.load_dll.dbg_offset;
|
|
||||||
event->u.LoadDll.nDebugInfoSize = data->info.load_dll.dbg_size;
|
|
||||||
event->u.LoadDll.lpImageName = data->info.load_dll.name;
|
|
||||||
event->u.LoadDll.fUnicode = data->info.load_dll.unicode;
|
|
||||||
if (data->info.load_dll.handle == -1) event->u.LoadDll.hFile = 0;
|
|
||||||
break;
|
|
||||||
case UNLOAD_DLL_DEBUG_EVENT:
|
|
||||||
event->u.UnloadDll.lpBaseOfDll = data->info.unload_dll.base;
|
|
||||||
break;
|
|
||||||
case OUTPUT_DEBUG_STRING_EVENT:
|
|
||||||
event->u.DebugString.lpDebugStringData = data->info.output_string.string;
|
|
||||||
event->u.DebugString.fUnicode = data->info.output_string.unicode;
|
|
||||||
event->u.DebugString.nDebugStringLength = data->info.output_string.length;
|
|
||||||
break;
|
|
||||||
case RIP_EVENT:
|
|
||||||
event->u.RipInfo.dwError = data->info.rip_info.error;
|
|
||||||
event->u.RipInfo.dwType = data->info.rip_info.type;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
server_protocol_error( "WaitForDebugEvent: bad code %d\n", data->code );
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SetLastError( ERROR_SEM_TIMEOUT );
|
||||||
return ret;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -131,18 +131,18 @@ struct new_process_request
|
||||||
IN handle_t hstdout; /* handle for stdout */
|
IN handle_t hstdout; /* handle for stdout */
|
||||||
IN handle_t hstderr; /* handle for stderr */
|
IN handle_t hstderr; /* handle for stderr */
|
||||||
IN int cmd_show; /* main window show mode */
|
IN int cmd_show; /* main window show mode */
|
||||||
|
OUT handle_t info; /* new process info handle */
|
||||||
IN VARARG(filename,string); /* file name of main exe */
|
IN VARARG(filename,string); /* file name of main exe */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Wait for the new process to start */
|
/* Retrieve information about a newly started process */
|
||||||
struct wait_process_request
|
struct get_new_process_info_request
|
||||||
{
|
{
|
||||||
REQUEST_HEADER; /* request header */
|
REQUEST_HEADER; /* request header */
|
||||||
|
IN handle_t info; /* info handle returned from new_process_request */
|
||||||
IN int pinherit; /* process handle inherit flag */
|
IN int pinherit; /* process handle inherit flag */
|
||||||
IN int tinherit; /* thread handle inherit flag */
|
IN int tinherit; /* thread handle inherit flag */
|
||||||
IN int timeout; /* wait timeout */
|
|
||||||
IN int cancel; /* cancel the process creation? */
|
|
||||||
OUT void* pid; /* process id */
|
OUT void* pid; /* process id */
|
||||||
OUT handle_t phandle; /* process handle (in the current process) */
|
OUT handle_t phandle; /* process handle (in the current process) */
|
||||||
OUT void* tid; /* thread id */
|
OUT void* tid; /* thread id */
|
||||||
|
@ -930,9 +930,10 @@ struct next_module_request
|
||||||
struct wait_debug_event_request
|
struct wait_debug_event_request
|
||||||
{
|
{
|
||||||
REQUEST_HEADER; /* request header */
|
REQUEST_HEADER; /* request header */
|
||||||
IN int timeout; /* timeout in ms */
|
IN int get_handle; /* should we alloc a handle for waiting? */
|
||||||
OUT void* pid; /* process id */
|
OUT void* pid; /* process id */
|
||||||
OUT void* tid; /* thread id */
|
OUT void* tid; /* thread id */
|
||||||
|
OUT handle_t wait; /* wait handle if no event ready */
|
||||||
OUT VARARG(event,debug_event); /* debug event data */
|
OUT VARARG(event,debug_event); /* debug event data */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1356,7 +1357,7 @@ struct async_result_request
|
||||||
enum request
|
enum request
|
||||||
{
|
{
|
||||||
REQ_NEW_PROCESS,
|
REQ_NEW_PROCESS,
|
||||||
REQ_WAIT_PROCESS,
|
REQ_GET_NEW_PROCESS_INFO,
|
||||||
REQ_NEW_THREAD,
|
REQ_NEW_THREAD,
|
||||||
REQ_BOOT_DONE,
|
REQ_BOOT_DONE,
|
||||||
REQ_INIT_PROCESS,
|
REQ_INIT_PROCESS,
|
||||||
|
@ -1471,7 +1472,7 @@ union generic_request
|
||||||
struct request_max_size max_size;
|
struct request_max_size max_size;
|
||||||
struct request_header header;
|
struct request_header header;
|
||||||
struct new_process_request new_process;
|
struct new_process_request new_process;
|
||||||
struct wait_process_request wait_process;
|
struct get_new_process_info_request get_new_process_info;
|
||||||
struct new_thread_request new_thread;
|
struct new_thread_request new_thread;
|
||||||
struct boot_done_request boot_done;
|
struct boot_done_request boot_done;
|
||||||
struct init_process_request init_process;
|
struct init_process_request init_process;
|
||||||
|
@ -1580,7 +1581,7 @@ union generic_request
|
||||||
struct async_result_request async_result;
|
struct async_result_request async_result;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 34
|
#define SERVER_PROTOCOL_VERSION 35
|
||||||
|
|
||||||
/* ### make_requests end ### */
|
/* ### make_requests end ### */
|
||||||
/* Everything above this line is generated automatically by tools/make_requests */
|
/* Everything above this line is generated automatically by tools/make_requests */
|
||||||
|
|
|
@ -743,6 +743,7 @@ BOOL PROCESS_Create( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env,
|
||||||
const char *unixdir = NULL;
|
const char *unixdir = NULL;
|
||||||
DOS_FULL_NAME full_dir, full_name;
|
DOS_FULL_NAME full_dir, full_name;
|
||||||
HANDLE load_done_evt = 0;
|
HANDLE load_done_evt = 0;
|
||||||
|
HANDLE process_info;
|
||||||
|
|
||||||
info->hThread = info->hProcess = 0;
|
info->hThread = info->hProcess = 0;
|
||||||
|
|
||||||
|
@ -797,6 +798,7 @@ BOOL PROCESS_Create( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env,
|
||||||
lstrcpynA( server_data_ptr(req), filename, MAX_PATH );
|
lstrcpynA( server_data_ptr(req), filename, MAX_PATH );
|
||||||
}
|
}
|
||||||
ret = !server_call( REQ_NEW_PROCESS );
|
ret = !server_call( REQ_NEW_PROCESS );
|
||||||
|
process_info = req->info;
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
if (!ret) return FALSE;
|
if (!ret) return FALSE;
|
||||||
|
@ -805,24 +807,30 @@ BOOL PROCESS_Create( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env,
|
||||||
|
|
||||||
pid = fork_and_exec( unixfilename, cmd_line, env, unixdir );
|
pid = fork_and_exec( unixfilename, cmd_line, env, unixdir );
|
||||||
|
|
||||||
SERVER_START_REQ
|
/* wait for the new process info to be ready */
|
||||||
|
|
||||||
|
ret = FALSE;
|
||||||
|
if ((pid != -1) && (WaitForSingleObject( process_info, 2000 ) == STATUS_WAIT_0))
|
||||||
{
|
{
|
||||||
struct wait_process_request *req = server_alloc_req( sizeof(*req), 0 );
|
SERVER_START_REQ
|
||||||
req->cancel = (pid == -1);
|
|
||||||
req->pinherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
|
|
||||||
req->tinherit = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle);
|
|
||||||
req->timeout = 2000;
|
|
||||||
if ((ret = !server_call( REQ_WAIT_PROCESS )) && (pid != -1))
|
|
||||||
{
|
{
|
||||||
info->dwProcessId = (DWORD)req->pid;
|
struct get_new_process_info_request *req = server_alloc_req( sizeof(*req), 0 );
|
||||||
info->dwThreadId = (DWORD)req->tid;
|
req->info = process_info;
|
||||||
info->hProcess = req->phandle;
|
req->pinherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
|
||||||
info->hThread = req->thandle;
|
req->tinherit = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle);
|
||||||
load_done_evt = req->event;
|
if ((ret = !server_call( REQ_GET_NEW_PROCESS_INFO )))
|
||||||
|
{
|
||||||
|
info->dwProcessId = (DWORD)req->pid;
|
||||||
|
info->dwThreadId = (DWORD)req->tid;
|
||||||
|
info->hProcess = req->phandle;
|
||||||
|
info->hThread = req->thandle;
|
||||||
|
load_done_evt = req->event;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
CloseHandle( process_info );
|
||||||
if (!ret || (pid == -1)) goto error;
|
if (!ret) goto error;
|
||||||
|
|
||||||
/* Wait until process is initialized (or initialization failed) */
|
/* Wait until process is initialized (or initialization failed) */
|
||||||
if (load_done_evt)
|
if (load_done_evt)
|
||||||
|
|
|
@ -241,37 +241,6 @@ static struct debug_event *find_event_to_send( struct debug_ctx *debug_ctx )
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build a reply for the wait_debug_event request */
|
|
||||||
static void build_wait_debug_reply( struct thread *thread, struct object *obj, int signaled )
|
|
||||||
{
|
|
||||||
struct wait_debug_event_request *req = get_req_ptr( thread );
|
|
||||||
|
|
||||||
if (obj)
|
|
||||||
{
|
|
||||||
struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
|
|
||||||
struct debug_event *event = find_event_to_send( debug_ctx );
|
|
||||||
size_t size = get_req_data_size(req);
|
|
||||||
|
|
||||||
/* the object that woke us has to be our debug context */
|
|
||||||
assert( obj->ops == &debug_ctx_ops );
|
|
||||||
assert( event );
|
|
||||||
|
|
||||||
event->state = EVENT_SENT;
|
|
||||||
event->sender->debug_event = event;
|
|
||||||
req->pid = event->sender->process;
|
|
||||||
req->tid = event->sender;
|
|
||||||
if (size > sizeof(debug_event_t)) size = sizeof(debug_event_t);
|
|
||||||
memcpy( get_req_data(req), &event->data, size );
|
|
||||||
set_req_data_size( req, size );
|
|
||||||
}
|
|
||||||
else /* timeout or error */
|
|
||||||
{
|
|
||||||
set_req_data_size( req, 0 );
|
|
||||||
req->pid = 0;
|
|
||||||
req->tid = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* build a reply for the send_event request */
|
/* build a reply for the send_event request */
|
||||||
static void build_exception_event_reply( struct thread *thread, struct object *obj, int signaled )
|
static void build_exception_event_reply( struct thread *thread, struct object *obj, int signaled )
|
||||||
{
|
{
|
||||||
|
@ -357,29 +326,6 @@ static void debug_ctx_destroy( struct object *obj )
|
||||||
while ((event = debug_ctx->event_head) != NULL) unlink_event( debug_ctx, event );
|
while ((event = debug_ctx->event_head) != NULL) unlink_event( debug_ctx, event );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wait for a debug event (or send a reply at once if one is pending) */
|
|
||||||
static int wait_for_debug_event( int timeout )
|
|
||||||
{
|
|
||||||
struct debug_ctx *debug_ctx = current->debug_ctx;
|
|
||||||
struct object *obj = &debug_ctx->obj;
|
|
||||||
int flags = 0;
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
if (!debug_ctx) /* current thread is not a debugger */
|
|
||||||
{
|
|
||||||
set_error( STATUS_INVALID_HANDLE );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (timeout != -1)
|
|
||||||
{
|
|
||||||
flags = SELECT_TIMEOUT;
|
|
||||||
gettimeofday( &tv, 0 );
|
|
||||||
add_timeout( &tv, timeout );
|
|
||||||
}
|
|
||||||
else tv.tv_sec = tv.tv_usec = 0;
|
|
||||||
return sleep_on( 1, &obj, flags, tv.tv_sec, tv.tv_usec, build_wait_debug_reply );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* continue a debug event */
|
/* continue a debug event */
|
||||||
static int continue_debug_event( struct process *process, struct thread *thread, int status )
|
static int continue_debug_event( struct process *process, struct thread *thread, int status )
|
||||||
{
|
{
|
||||||
|
@ -539,11 +485,33 @@ void debug_exit_thread( struct thread *thread )
|
||||||
/* Wait for a debug event */
|
/* Wait for a debug event */
|
||||||
DECL_HANDLER(wait_debug_event)
|
DECL_HANDLER(wait_debug_event)
|
||||||
{
|
{
|
||||||
if (!wait_for_debug_event( req->timeout ))
|
struct debug_ctx *debug_ctx = current->debug_ctx;
|
||||||
|
struct debug_event *event;
|
||||||
|
|
||||||
|
if (!debug_ctx) /* current thread is not a debugger */
|
||||||
{
|
{
|
||||||
req->pid = NULL;
|
set_error( STATUS_INVALID_HANDLE );
|
||||||
req->tid = NULL;
|
return;
|
||||||
|
}
|
||||||
|
req->wait = 0;
|
||||||
|
if ((event = find_event_to_send( debug_ctx )))
|
||||||
|
{
|
||||||
|
size_t size = get_req_data_size(req);
|
||||||
|
event->state = EVENT_SENT;
|
||||||
|
event->sender->debug_event = event;
|
||||||
|
req->pid = event->sender->process;
|
||||||
|
req->tid = event->sender;
|
||||||
|
if (size > sizeof(debug_event_t)) size = sizeof(debug_event_t);
|
||||||
|
memcpy( get_req_data(req), &event->data, size );
|
||||||
|
set_req_data_size( req, size );
|
||||||
|
}
|
||||||
|
else /* no event ready */
|
||||||
|
{
|
||||||
|
req->pid = 0;
|
||||||
|
req->tid = 0;
|
||||||
set_req_data_size( req, 0 );
|
set_req_data_size( req, 0 );
|
||||||
|
if (req->get_handle)
|
||||||
|
req->wait = alloc_handle( current->process, debug_ctx, SYNCHRONIZE, FALSE );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ struct startup_info
|
||||||
int cmd_show; /* main window show mode */
|
int cmd_show; /* main window show mode */
|
||||||
struct file *exe_file; /* file handle for main exe */
|
struct file *exe_file; /* file handle for main exe */
|
||||||
char *filename; /* file name for main exe */
|
char *filename; /* file name for main exe */
|
||||||
|
struct thread *owner; /* owner thread (the one that created the new process) */
|
||||||
struct process *process; /* created process */
|
struct process *process; /* created process */
|
||||||
struct thread *thread; /* created thread */
|
struct thread *thread; /* created thread */
|
||||||
};
|
};
|
||||||
|
@ -319,6 +320,11 @@ static void startup_info_destroy( struct object *obj )
|
||||||
if (info->exe_file) release_object( info->exe_file );
|
if (info->exe_file) release_object( info->exe_file );
|
||||||
if (info->process) release_object( info->process );
|
if (info->process) release_object( info->process );
|
||||||
if (info->thread) release_object( info->thread );
|
if (info->thread) release_object( info->thread );
|
||||||
|
if (info->owner)
|
||||||
|
{
|
||||||
|
info->owner->info = NULL;
|
||||||
|
release_object( info->owner );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void startup_info_dump( struct object *obj, int verbose )
|
static void startup_info_dump( struct object *obj, int verbose )
|
||||||
|
@ -337,33 +343,6 @@ static int startup_info_signaled( struct object *obj, struct thread *thread )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* build a reply for the wait_process request */
|
|
||||||
static void build_wait_process_reply( struct thread *thread, struct object *obj, int signaled )
|
|
||||||
{
|
|
||||||
struct wait_process_request *req = get_req_ptr( thread );
|
|
||||||
if (obj)
|
|
||||||
{
|
|
||||||
struct startup_info *info = (struct startup_info *)obj;
|
|
||||||
assert( obj->ops == &startup_info_ops );
|
|
||||||
|
|
||||||
req->pid = get_process_id( info->process );
|
|
||||||
req->tid = get_thread_id( info->thread );
|
|
||||||
req->phandle = alloc_handle( thread->process, info->process,
|
|
||||||
PROCESS_ALL_ACCESS, req->pinherit );
|
|
||||||
req->thandle = alloc_handle( thread->process, info->thread,
|
|
||||||
THREAD_ALL_ACCESS, req->tinherit );
|
|
||||||
if (info->process->init_event)
|
|
||||||
req->event = alloc_handle( thread->process, info->process->init_event,
|
|
||||||
EVENT_ALL_ACCESS, 0 );
|
|
||||||
else
|
|
||||||
req->event = 0;
|
|
||||||
|
|
||||||
/* FIXME: set_error */
|
|
||||||
}
|
|
||||||
release_object( thread->info );
|
|
||||||
thread->info = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get a process from an id (and increment the refcount) */
|
/* get a process from an id (and increment the refcount) */
|
||||||
struct process *get_process_from_id( void *id )
|
struct process *get_process_from_id( void *id )
|
||||||
{
|
{
|
||||||
|
@ -731,52 +710,52 @@ DECL_HANDLER(new_process)
|
||||||
info->cmd_show = req->cmd_show;
|
info->cmd_show = req->cmd_show;
|
||||||
info->exe_file = NULL;
|
info->exe_file = NULL;
|
||||||
info->filename = NULL;
|
info->filename = NULL;
|
||||||
|
info->owner = (struct thread *)grab_object( current );
|
||||||
info->process = NULL;
|
info->process = NULL;
|
||||||
info->thread = NULL;
|
info->thread = NULL;
|
||||||
|
|
||||||
if (req->exe_file &&
|
if (req->exe_file &&
|
||||||
!(info->exe_file = get_file_obj( current->process, req->exe_file, GENERIC_READ )))
|
!(info->exe_file = get_file_obj( current->process, req->exe_file, GENERIC_READ )))
|
||||||
{
|
goto done;
|
||||||
release_object( info );
|
|
||||||
return;
|
if (!(info->filename = mem_alloc( len + 1 ))) goto done;
|
||||||
}
|
|
||||||
|
|
||||||
if (!(info->filename = mem_alloc( len + 1 )))
|
|
||||||
{
|
|
||||||
release_object( info );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memcpy( info->filename, get_req_data(req), len );
|
memcpy( info->filename, get_req_data(req), len );
|
||||||
info->filename[len] = 0;
|
info->filename[len] = 0;
|
||||||
current->info = info;
|
current->info = info;
|
||||||
|
req->info = alloc_handle( current->process, info, SYNCHRONIZE, FALSE );
|
||||||
|
|
||||||
|
done:
|
||||||
|
release_object( info );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for the new process to start */
|
/* Retrieve information about a newly started process */
|
||||||
DECL_HANDLER(wait_process)
|
DECL_HANDLER(get_new_process_info)
|
||||||
{
|
{
|
||||||
if (!current->info)
|
struct startup_info *info;
|
||||||
|
|
||||||
|
req->event = 0;
|
||||||
|
|
||||||
|
if ((info = (struct startup_info *)get_handle_obj( current->process, req->info,
|
||||||
|
0, &startup_info_ops )))
|
||||||
{
|
{
|
||||||
fatal_protocol_error( current, "wait_process: no process is being created\n" );
|
req->pid = get_process_id( info->process );
|
||||||
return;
|
req->tid = get_thread_id( info->thread );
|
||||||
}
|
req->phandle = alloc_handle( current->process, info->process,
|
||||||
req->pid = 0;
|
PROCESS_ALL_ACCESS, req->pinherit );
|
||||||
req->tid = 0;
|
req->thandle = alloc_handle( current->process, info->thread,
|
||||||
req->phandle = 0;
|
THREAD_ALL_ACCESS, req->tinherit );
|
||||||
req->thandle = 0;
|
if (info->process->init_event)
|
||||||
req->event = 0;
|
req->event = alloc_handle( current->process, info->process->init_event,
|
||||||
if (req->cancel)
|
EVENT_ALL_ACCESS, 0 );
|
||||||
{
|
release_object( info );
|
||||||
release_object( current->info );
|
|
||||||
current->info = NULL;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct timeval timeout;
|
req->pid = 0;
|
||||||
struct object *obj = ¤t->info->obj;
|
req->tid = 0;
|
||||||
gettimeofday( &timeout, 0 );
|
req->phandle = 0;
|
||||||
add_timeout( &timeout, req->timeout );
|
req->thandle = 0;
|
||||||
sleep_on( 1, &obj, SELECT_TIMEOUT, timeout.tv_sec, timeout.tv_usec,
|
|
||||||
build_wait_process_reply );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ inline static void set_req_data_size( const void *req, size_t size )
|
||||||
/* ### make_requests begin ### */
|
/* ### make_requests begin ### */
|
||||||
|
|
||||||
DECL_HANDLER(new_process);
|
DECL_HANDLER(new_process);
|
||||||
DECL_HANDLER(wait_process);
|
DECL_HANDLER(get_new_process_info);
|
||||||
DECL_HANDLER(new_thread);
|
DECL_HANDLER(new_thread);
|
||||||
DECL_HANDLER(boot_done);
|
DECL_HANDLER(boot_done);
|
||||||
DECL_HANDLER(init_process);
|
DECL_HANDLER(init_process);
|
||||||
|
@ -185,7 +185,7 @@ typedef void (*req_handler)( void *req );
|
||||||
static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
||||||
{
|
{
|
||||||
(req_handler)req_new_process,
|
(req_handler)req_new_process,
|
||||||
(req_handler)req_wait_process,
|
(req_handler)req_get_new_process_info,
|
||||||
(req_handler)req_new_thread,
|
(req_handler)req_new_thread,
|
||||||
(req_handler)req_boot_done,
|
(req_handler)req_boot_done,
|
||||||
(req_handler)req_init_process,
|
(req_handler)req_init_process,
|
||||||
|
|
|
@ -275,15 +275,19 @@ static void dump_new_process_request( const struct new_process_request *req )
|
||||||
cur_pos += dump_varargs_string( req );
|
cur_pos += dump_varargs_string( req );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_wait_process_request( const struct wait_process_request *req )
|
static void dump_new_process_reply( const struct new_process_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " pinherit=%d,", req->pinherit );
|
fprintf( stderr, " info=%d", req->info );
|
||||||
fprintf( stderr, " tinherit=%d,", req->tinherit );
|
|
||||||
fprintf( stderr, " timeout=%d,", req->timeout );
|
|
||||||
fprintf( stderr, " cancel=%d", req->cancel );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_wait_process_reply( const struct wait_process_request *req )
|
static void dump_get_new_process_info_request( const struct get_new_process_info_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " info=%d,", req->info );
|
||||||
|
fprintf( stderr, " pinherit=%d,", req->pinherit );
|
||||||
|
fprintf( stderr, " tinherit=%d", req->tinherit );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_get_new_process_info_reply( const struct get_new_process_info_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " pid=%p,", req->pid );
|
fprintf( stderr, " pid=%p,", req->pid );
|
||||||
fprintf( stderr, " phandle=%d,", req->phandle );
|
fprintf( stderr, " phandle=%d,", req->phandle );
|
||||||
|
@ -1050,13 +1054,14 @@ static void dump_next_module_reply( const struct next_module_request *req )
|
||||||
|
|
||||||
static void dump_wait_debug_event_request( const struct wait_debug_event_request *req )
|
static void dump_wait_debug_event_request( const struct wait_debug_event_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " timeout=%d", req->timeout );
|
fprintf( stderr, " get_handle=%d", req->get_handle );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_wait_debug_event_reply( const struct wait_debug_event_request *req )
|
static void dump_wait_debug_event_reply( const struct wait_debug_event_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " pid=%p,", req->pid );
|
fprintf( stderr, " pid=%p,", req->pid );
|
||||||
fprintf( stderr, " tid=%p,", req->tid );
|
fprintf( stderr, " tid=%p,", req->tid );
|
||||||
|
fprintf( stderr, " wait=%d,", req->wait );
|
||||||
fprintf( stderr, " event=" );
|
fprintf( stderr, " event=" );
|
||||||
cur_pos += dump_varargs_debug_event( req );
|
cur_pos += dump_varargs_debug_event( req );
|
||||||
}
|
}
|
||||||
|
@ -1474,7 +1479,7 @@ static void dump_async_result_request( const struct async_result_request *req )
|
||||||
|
|
||||||
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_new_process_request,
|
(dump_func)dump_new_process_request,
|
||||||
(dump_func)dump_wait_process_request,
|
(dump_func)dump_get_new_process_info_request,
|
||||||
(dump_func)dump_new_thread_request,
|
(dump_func)dump_new_thread_request,
|
||||||
(dump_func)dump_boot_done_request,
|
(dump_func)dump_boot_done_request,
|
||||||
(dump_func)dump_init_process_request,
|
(dump_func)dump_init_process_request,
|
||||||
|
@ -1584,8 +1589,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)0,
|
(dump_func)dump_new_process_reply,
|
||||||
(dump_func)dump_wait_process_reply,
|
(dump_func)dump_get_new_process_info_reply,
|
||||||
(dump_func)dump_new_thread_reply,
|
(dump_func)dump_new_thread_reply,
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
(dump_func)dump_init_process_reply,
|
(dump_func)dump_init_process_reply,
|
||||||
|
@ -1696,7 +1701,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
|
|
||||||
static const char * const req_names[REQ_NB_REQUESTS] = {
|
static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
"new_process",
|
"new_process",
|
||||||
"wait_process",
|
"get_new_process_info",
|
||||||
"new_thread",
|
"new_thread",
|
||||||
"boot_done",
|
"boot_done",
|
||||||
"init_process",
|
"init_process",
|
||||||
|
|
Loading…
Reference in New Issue