Commit 9a0e28f1 authored by Alexandre Julliard's avatar Alexandre Julliard

Fixed a couple of file descriptor leaks.

Always call USER signal proc in the right context. Cleaned up THREAD_Create.
parent f97576b6
......@@ -158,7 +158,7 @@ extern void ENV_FreeEnvironment( PDB *pdb );
/* scheduler/process.c */
extern BOOL PROCESS_Init( BOOL win32 );
extern PDB *PROCESS_IdToPDB( DWORD id );
extern void PROCESS_CallUserSignalProc( UINT uCode, DWORD dwThreadId, HMODULE hModule );
extern void PROCESS_CallUserSignalProc( UINT uCode, HMODULE hModule );
extern PDB *PROCESS_Create( struct _NE_MODULE *pModule, HFILE hFile,
LPCSTR cmd_line, LPCSTR env,
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
......
......@@ -104,7 +104,8 @@ typedef struct
/* Create a new process from the context of the parent */
struct new_process_request
{
IN int inherit; /* inherit flag */
IN int pinherit; /* process handle inherit flag */
IN int tinherit; /* thread handle inherit flag */
IN int inherit_all; /* inherit all handles from parent */
IN int create_flags; /* creation flags */
IN int start_flags; /* flags from startup info */
......@@ -234,7 +235,9 @@ struct set_process_info_request
struct get_thread_info_request
{
IN int handle; /* thread handle */
IN void* tid_in; /* thread id (optional) */
OUT void* tid; /* server thread id */
OUT void* teb; /* thread teb pointer */
OUT int exit_code; /* thread exit code */
OUT int priority; /* thread priority level */
};
......@@ -1205,7 +1208,7 @@ enum request
REQ_NB_REQUESTS
};
#define SERVER_PROTOCOL_VERSION 4
#define SERVER_PROTOCOL_VERSION 5
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
......
......@@ -122,9 +122,8 @@ typedef struct _TEB
/* scheduler/thread.c */
extern TEB *THREAD_CreateInitialThread( struct _PDB *pdb, int server_fd );
extern TEB *THREAD_Create( struct _PDB *pdb, int fd, DWORD flags,
DWORD stack_size, BOOL alloc_stack16,
struct _SECURITY_ATTRIBUTES *sa, int *server_handle );
extern TEB *THREAD_Create( struct _PDB *pdb, void *tid, int fd, DWORD flags,
DWORD stack_size, BOOL alloc_stack16 );
extern BOOL THREAD_IsWin16( TEB *thdb );
extern TEB *THREAD_IdToTEB( DWORD id );
......
......@@ -1278,7 +1278,7 @@ static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep )
/* Free the objects owned by the DLL module */
TASK_CallTaskSignalProc( USIG16_DLL_UNLOAD, hModule );
PROCESS_CallUserSignalProc( USIG_DLL_UNLOAD_WIN16, 0, hModule );
PROCESS_CallUserSignalProc( USIG_DLL_UNLOAD_WIN16, hModule );
}
else
call_wep = FALSE; /* We are freeing a task -> no more WEPs */
......
......@@ -468,9 +468,9 @@ void TASK_KillTask( HTASK16 hTask )
/* Perform USER cleanup */
TASK_CallTaskSignalProc( USIG16_TERMINATION, hTask );
PROCESS_CallUserSignalProc( USIG_PROCESS_EXIT, 0, 0 );
PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, GetCurrentThreadId(), 0 );
PROCESS_CallUserSignalProc( USIG_PROCESS_DESTROY, 0, 0 );
PROCESS_CallUserSignalProc( USIG_PROCESS_EXIT, 0 );
PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, 0 );
PROCESS_CallUserSignalProc( USIG_PROCESS_DESTROY, 0 );
if (nTaskCount <= 1)
{
......
......@@ -157,7 +157,7 @@ PDB *PROCESS_IdToPDB( DWORD pid )
* USIG_FLAGS_FAULT
* The signal is being sent due to a fault.
*/
void PROCESS_CallUserSignalProc( UINT uCode, DWORD dwThreadId, HMODULE hModule )
void PROCESS_CallUserSignalProc( UINT uCode, HMODULE hModule )
{
DWORD flags = PROCESS_Current()->flags;
DWORD startup_flags = PROCESS_Current()->env_db->startup_info->dwFlags;
......@@ -192,7 +192,7 @@ void PROCESS_CallUserSignalProc( UINT uCode, DWORD dwThreadId, HMODULE hModule )
if ( Callout.UserSignalProc )
{
if ( uCode == USIG_THREAD_INIT || uCode == USIG_THREAD_EXIT )
Callout.UserSignalProc( uCode, dwThreadId, dwFlags, hModule );
Callout.UserSignalProc( uCode, GetCurrentThreadId(), dwFlags, hModule );
else
Callout.UserSignalProc( uCode, GetCurrentProcessId(), dwFlags, hModule );
}
......@@ -434,10 +434,10 @@ void PROCESS_Start(void)
* in the case of a 16-bit process. Thus, we send the signal here.
*/
PROCESS_CallUserSignalProc( USIG_PROCESS_CREATE, 0, 0 );
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, GetCurrentThreadId(), 0 );
PROCESS_CallUserSignalProc( USIG_PROCESS_INIT, 0, 0 );
PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0, 0 );
PROCESS_CallUserSignalProc( USIG_PROCESS_CREATE, 0 );
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0 );
PROCESS_CallUserSignalProc( USIG_PROCESS_INIT, 0 );
PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0 );
/* Signal the parent process to continue */
req->module = (void *)pModule->module32;
......@@ -461,7 +461,7 @@ void PROCESS_Start(void)
/* 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 );
PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0 );
switch ( type )
{
......@@ -503,7 +503,7 @@ PDB *PROCESS_Create( NE_MODULE *pModule, HFILE hFile, LPCSTR cmd_line, LPCSTR en
HANDLE handles[2], load_done_evt = 0;
DWORD exitcode, size;
BOOL alloc_stack16;
int server_thandle, fd = -1;
int fd = -1;
struct new_process_request *req = get_req_buffer();
TEB *teb = NULL;
PDB *parent = PROCESS_Current();
......@@ -515,7 +515,8 @@ PDB *PROCESS_Create( NE_MODULE *pModule, HFILE hFile, LPCSTR cmd_line, LPCSTR en
/* Create the process on the server side */
req->inherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
req->pinherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
req->tinherit = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle);
req->inherit_all = inherit;
req->create_flags = flags;
req->start_flags = startup->dwFlags;
......@@ -537,7 +538,6 @@ PDB *PROCESS_Create( NE_MODULE *pModule, HFILE hFile, LPCSTR cmd_line, LPCSTR en
req->env_ptr = (void*)env; /* FIXME: hack */
lstrcpynA( req->cmdline, cmd_line, server_remaining(req->cmdline) );
if (server_call_fd( REQ_NEW_PROCESS, -1, &fd )) goto error;
fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
pdb->server_pid = req->pid;
info->hProcess = req->phandle;
info->dwProcessId = (DWORD)req->pid;
......@@ -567,8 +567,8 @@ PDB *PROCESS_Create( NE_MODULE *pModule, HFILE hFile, LPCSTR cmd_line, LPCSTR en
/* Create the main thread */
if (!(teb = THREAD_Create( pdb, fd, flags & CREATE_SUSPENDED, size,
alloc_stack16, tsa, &server_thandle ))) goto error;
if (!(teb = THREAD_Create( pdb, req->tid, fd, flags & CREATE_SUSPENDED,
size, alloc_stack16 ))) goto error;
teb->tid = (void *)info->dwThreadId;
teb->startup = PROCESS_Start;
fd = -1; /* don't close it */
......
......@@ -49,8 +49,13 @@ CRITICAL_SECTION X11DRV_CritSection = { 0, };
# define CLONE_SIGHAND 0x00000800
# define CLONE_PID 0x00001000
# endif /* CLONE_VM */
# define PER_THREAD_FILE_HANDLES
#endif /* linux */
#ifdef HAVE_RFORK
# define PER_THREAD_FILE_HANDLES
#endif
static int init_done;
#ifndef NO_REENTRANT_LIBC
......@@ -125,7 +130,12 @@ void SYSDEPS_SetCurThread( TEB *teb )
*/
static void SYSDEPS_StartThread( TEB *teb )
{
int parent_socket = -1;
#ifdef PER_THREAD_FILE_HANDLES
parent_socket = NtCurrentTeb()->socket;
#endif
SYSDEPS_SetCurThread( teb );
if (parent_socket != -1) close( parent_socket );
CLIENT_InitThread();
SIGNAL_Init();
__TRY
......@@ -205,8 +215,11 @@ int SYSDEPS_SpawnThread( TEB *teb )
*/
void SYSDEPS_ExitThread( int status )
{
#ifdef HAVE__LWP_CREATE
#ifndef PER_THREAD_FILE_HANDLES
/* otherwise it will be closed automagically by _exit */
close( NtCurrentTeb()->socket );
#endif
#ifdef HAVE__LWP_CREATE
_lwp_exit();
#endif
_exit( status );
......
......@@ -31,14 +31,11 @@
#include "queue.h"
#include "hook.h"
DEFAULT_DEBUG_CHANNEL(thread)
DEFAULT_DEBUG_CHANNEL(thread);
/* TEB of the initial thread */
static TEB initial_teb;
/* Global thread list (FIXME: not thread-safe) */
TEB *THREAD_First = &initial_teb;
/***********************************************************************
* THREAD_IsWin16
*/
......@@ -54,14 +51,13 @@ BOOL THREAD_IsWin16( TEB *teb )
*/
TEB *THREAD_IdToTEB( DWORD id )
{
TEB *teb = THREAD_First;
struct get_thread_info_request *req = get_req_buffer();
if (!id || id == GetCurrentThreadId()) return NtCurrentTeb();
req->handle = -1;
req->tid_in = (void *)id;
if (!server_call_noerr( REQ_GET_THREAD_INFO )) return req->teb;
if (!id) return NtCurrentTeb();
while (teb)
{
if ((DWORD)teb->tid == id) return teb;
teb = teb->next;
}
/* Allow task handles to be used; convert to main thread */
if ( IsTask16( id ) )
{
......@@ -78,8 +74,7 @@ TEB *THREAD_IdToTEB( DWORD id )
*
* Initialization of a newly created TEB.
*/
static BOOL THREAD_InitTEB( TEB *teb, DWORD stack_size, BOOL alloc_stack16,
LPSECURITY_ATTRIBUTES sa )
static BOOL THREAD_InitTEB( TEB *teb, DWORD stack_size, BOOL alloc_stack16 )
{
DWORD old_prot;
......@@ -142,25 +137,18 @@ error:
void CALLBACK THREAD_FreeTEB( ULONG_PTR arg )
{
TEB *teb = (TEB *)arg;
TEB **pptr = &THREAD_First;
TRACE("(%p) called\n", teb );
SERVICE_Delete( teb->cleanup );
PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, (DWORD)teb->tid, 0 );
while (*pptr && (*pptr != teb)) pptr = &(*pptr)->next;
if (*pptr) *pptr = teb->next;
/* Free the associated memory */
if (teb->stack_sel) SELECTOR_FreeBlock( teb->stack_sel, 1 );
SELECTOR_FreeBlock( teb->teb_sel, 1 );
close( teb->socket );
if (teb->buffer) munmap( teb->buffer, teb->buffer_size );
if (teb->debug_info) HeapFree( GetProcessHeap(), 0, teb->debug_info );
VirtualFree( teb->stack_base, 0, MEM_RELEASE );
VirtualFree( teb, 0, MEM_FREE );
VirtualFree( teb, 0, MEM_RELEASE );
}
......@@ -192,7 +180,7 @@ TEB *THREAD_CreateInitialThread( PDB *pdb, int server_fd )
/* Now proceed with normal initialization */
if (CLIENT_InitThread()) return NULL;
if (!THREAD_InitTEB( &initial_teb, 0, TRUE, NULL )) return NULL;
if (!THREAD_InitTEB( &initial_teb, 0, TRUE )) return NULL;
return &initial_teb;
}
......@@ -206,12 +194,9 @@ TEB *THREAD_CreateInitialThread( PDB *pdb, int server_fd )
* allocate in this area and don't support a granularity of 4kb
* yet we leave it to VirtualAlloc to choose an address.
*/
TEB *THREAD_Create( PDB *pdb, int fd, DWORD flags, DWORD stack_size, BOOL alloc_stack16,
LPSECURITY_ATTRIBUTES sa, int *server_handle )
TEB *THREAD_Create( PDB *pdb, void *tid, int fd, DWORD flags,
DWORD stack_size, BOOL alloc_stack16 )
{
struct new_thread_request *req = get_req_buffer();
HANDLE cleanup_object;
TEB *teb = VirtualAlloc(0, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!teb) return NULL;
teb->except = (void *)-1;
......@@ -222,45 +207,24 @@ TEB *THREAD_Create( PDB *pdb, int fd, DWORD flags, DWORD stack_size, BOOL alloc_
teb->process = pdb;
teb->exit_code = STILL_ACTIVE;
teb->socket = fd;
teb->tid = tid;
fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
/* Allocate the TEB selector (%fs register) */
*server_handle = -1;
teb->teb_sel = SELECTOR_AllocBlock( teb, 0x1000, SEGMENT_DATA, TRUE, FALSE );
if (!teb->teb_sel) goto error;
/* Create the thread on the server side */
if (teb->socket == -1)
{
req->suspend = ((flags & CREATE_SUSPENDED) != 0);
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
if (server_call_fd( REQ_NEW_THREAD, -1, &teb->socket )) goto error;
teb->tid = req->tid;
*server_handle = req->handle;
fcntl( teb->socket, F_SETFD, 1 ); /* set close on exec flag */
}
/* Do the rest of the initialization */
if (!THREAD_InitTEB( teb, stack_size, alloc_stack16, sa )) goto error;
teb->next = THREAD_First;
THREAD_First = teb;
/* Install cleanup handler */
if ( !DuplicateHandle( GetCurrentProcess(), *server_handle,
GetCurrentProcess(), &cleanup_object,
0, FALSE, DUPLICATE_SAME_ACCESS ) ) goto error;
teb->cleanup = SERVICE_AddObject( cleanup_object, THREAD_FreeTEB, (ULONG_PTR)teb );
if (!THREAD_InitTEB( teb, stack_size, alloc_stack16 )) goto error;
TRACE("(%p) succeeded\n", teb);
return teb;
error:
if (*server_handle != -1) CloseHandle( *server_handle );
if (teb->teb_sel) SELECTOR_FreeBlock( teb->teb_sel, 1 );
if (teb->socket != -1) close( teb->socket );
VirtualFree( teb, 0, MEM_FREE );
VirtualFree( teb, 0, MEM_RELEASE );
return NULL;
}
......@@ -272,8 +236,17 @@ error:
*/
static void THREAD_Start(void)
{
HANDLE cleanup_object;
LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)NtCurrentTeb()->entry_point;
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, (DWORD)NtCurrentTeb()->tid, 0 );
/* install cleanup handler */
if (DuplicateHandle( GetCurrentProcess(), GetCurrentThread(),
GetCurrentProcess(), &cleanup_object,
0, FALSE, DUPLICATE_SAME_ACCESS ))
NtCurrentTeb()->cleanup = SERVICE_AddObject( cleanup_object, THREAD_FreeTEB,
(ULONG_PTR)NtCurrentTeb() );
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0 );
PE_InitTls();
MODULE_DllThreadAttach( NULL );
ExitThread( func( NtCurrentTeb()->entry_arg ) );
......@@ -287,9 +260,20 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack,
LPTHREAD_START_ROUTINE start, LPVOID param,
DWORD flags, LPDWORD id )
{
int handle = -1;
TEB *teb = THREAD_Create( PROCESS_Current(), -1, flags, stack, TRUE, sa, &handle );
if (!teb) return 0;
struct new_thread_request *req = get_req_buffer();
int socket, handle = -1;
TEB *teb;
req->suspend = ((flags & CREATE_SUSPENDED) != 0);
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
if (server_call_fd( REQ_NEW_THREAD, -1, &socket )) return 0;
handle = req->handle;
if (!(teb = THREAD_Create( PROCESS_Current(), req->tid, socket, flags, stack, TRUE )))
{
close( socket );
return 0;
}
teb->tibflags |= TEBF_WIN32;
teb->entry_point = start;
teb->entry_arg = param;
......@@ -351,6 +335,7 @@ void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
else
{
MODULE_DllThreadDetach( NULL );
PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, 0 );
SYSDEPS_ExitThread( code );
}
}
......@@ -556,6 +541,7 @@ INT WINAPI GetThreadPriority(
INT ret = THREAD_PRIORITY_ERROR_RETURN;
struct get_thread_info_request *req = get_req_buffer();
req->handle = hthread;
req->tid_in = 0;
if (!server_call( REQ_GET_THREAD_INFO )) ret = req->priority;
return ret;
}
......@@ -611,6 +597,7 @@ BOOL WINAPI TerminateThread(
req->exit_code = exitcode;
if ((ret = !server_call( REQ_TERMINATE_THREAD )) && req->self)
{
PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, 0 );
if (req->last) exit( exitcode );
else SYSDEPS_ExitThread( exitcode );
}
......@@ -632,6 +619,7 @@ BOOL WINAPI GetExitCodeThread(
BOOL ret = FALSE;
struct get_thread_info_request *req = get_req_buffer();
req->handle = hthread;
req->tid_in = 0;
if (!server_call( REQ_GET_THREAD_INFO ))
{
if (exitcode) *exitcode = req->exit_code;
......
......@@ -68,7 +68,8 @@ static int set_creation_info( struct process *process, struct new_process_reques
else /* no request, use defaults */
{
req = process->info;
req->inherit = 0;
req->pinherit = 0;
req->tinherit = 0;
req->inherit_all = 0;
req->create_flags = CREATE_NEW_CONSOLE;
req->start_flags = STARTF_USESTDHANDLES;
......@@ -595,11 +596,11 @@ DECL_HANDLER(new_process)
if ((thread = create_process( sock[0], current->process, req, req->cmdline, len )))
{
int phandle = alloc_handle( current->process, thread->process,
PROCESS_ALL_ACCESS, req->inherit );
PROCESS_ALL_ACCESS, req->pinherit );
if ((req->phandle = phandle) != -1)
{
if ((req->thandle = alloc_handle( current->process, thread,
THREAD_ALL_ACCESS, req->inherit )) != -1)
THREAD_ALL_ACCESS, req->tinherit )) != -1)
{
/* thread object will be released when the thread gets killed */
set_reply_fd( current, sock[1] );
......
......@@ -576,6 +576,8 @@ void kill_thread( struct thread *thread, int violent_death )
wake_up( &thread->obj, 0 );
detach_thread( thread, violent_death ? SIGTERM : 0 );
remove_select_user( &thread->obj );
munmap( thread->buffer, MAX_REQUEST_LENGTH );
thread->buffer = (void *)-1;
release_object( thread );
}
......@@ -663,10 +665,15 @@ DECL_HANDLER(terminate_thread)
DECL_HANDLER(get_thread_info)
{
struct thread *thread;
int handle = req->handle;
if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
if (handle == -1) thread = get_thread_from_id( req->tid_in );
else thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION );
if (thread)
{
req->tid = thread;
req->tid = get_thread_id( thread );
req->teb = thread->teb;
req->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STILL_ACTIVE;
req->priority = thread->priority;
release_object( thread );
......
......@@ -204,7 +204,8 @@ typedef void (*dump_func)( const void *req );
static void dump_new_process_request( const struct new_process_request *req )
{
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " pinherit=%d,", req->pinherit );
fprintf( stderr, " tinherit=%d,", req->tinherit );
fprintf( stderr, " inherit_all=%d,", req->inherit_all );
fprintf( stderr, " create_flags=%d,", req->create_flags );
fprintf( stderr, " start_flags=%d,", req->start_flags );
......@@ -339,12 +340,14 @@ static void dump_set_process_info_request( const struct set_process_info_request
static void dump_get_thread_info_request( const struct get_thread_info_request *req )
{
fprintf( stderr, " handle=%d", req->handle );
fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " tid_in=%p", req->tid_in );
}
static void dump_get_thread_info_reply( const struct get_thread_info_request *req )
{
fprintf( stderr, " tid=%p,", req->tid );
fprintf( stderr, " teb=%p,", req->teb );
fprintf( stderr, " exit_code=%d,", req->exit_code );
fprintf( stderr, " priority=%d", req->priority );
}
......
......@@ -239,7 +239,7 @@ WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
break;
case USIG_PROCESS_CREATE:
pdb = PROCESS_IdToPDB( dwThreadOrProcessID );
pdb = PROCESS_Current();
/* Create the idle event for the process. We have just one idle_event for all
win16 processes, while each win32 process has its own */
......@@ -264,8 +264,7 @@ WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
case USIG_PROCESS_LOADED:
break;
case USIG_PROCESS_RUNNING:
pdb = PROCESS_IdToPDB ( dwThreadOrProcessID );
SetEvent ( pdb->idle_event );
SetEvent ( PROCESS_Current()->idle_event );
break;
case USIG_PROCESS_EXIT:
......@@ -275,7 +274,7 @@ WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
hInst = GetProcessDword( dwThreadOrProcessID, GPD_HINSTANCE16 );
USER_AppExit( hInst );
pdb = PROCESS_IdToPDB( dwThreadOrProcessID );
pdb = PROCESS_Current();
if ( ! (pdb->flags & PDB32_WIN16_PROC) ) {
TRACE_(win)("destroying win32 idle event: %x\n", pdb->idle_event );
CloseHandle ( pdb->idle_event );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment