Changed process initialisation to use the new server requests.

Started to move the process init to the right context, not finished yet.
This commit is contained in:
Alexandre Julliard 1999-03-21 19:26:25 +00:00
parent f692d44607
commit f016752b45
6 changed files with 245 additions and 149 deletions

View file

@ -96,10 +96,11 @@ typedef struct _THDB
CRITICAL_SECTION *sys_mutex[4];/* 1e8 Syslevel mutex pointers */ CRITICAL_SECTION *sys_mutex[4];/* 1e8 Syslevel mutex pointers */
DWORD unknown6[2]; /* 1f8 Unknown */ DWORD unknown6[2]; /* 1f8 Unknown */
/* The following are Wine-specific fields */ /* The following are Wine-specific fields */
int socket; /* 200 Socket for server communication */ int socket; /* Socket for server communication */
unsigned int seq; /* Server sequence number */ unsigned int seq; /* Server sequence number */
void *server_tid; /* Server id for this thread */ void *server_tid; /* Server id for this thread */
struct _THDB *next; /* Global thread list */ void (*startup)(void); /* Thread startup routine */
struct _THDB *next; /* Global thread list */
} THDB; } THDB;
/* The pseudo handle value returned by GetCurrentThread */ /* The pseudo handle value returned by GetCurrentThread */
@ -115,16 +116,13 @@ extern THDB *pCurrentThread;
/* scheduler/thread.c */ /* scheduler/thread.c */
extern THDB *THREAD_CreateInitialThread( struct _PDB *pdb ); extern THDB *THREAD_CreateInitialThread( struct _PDB *pdb, int server_fd );
extern THDB *THREAD_Create( struct _PDB *pdb, DWORD flags, extern THDB *THREAD_Create( struct _PDB *pdb, DWORD flags,
DWORD stack_size, BOOL alloc_stack16, DWORD stack_size, BOOL alloc_stack16,
LPSECURITY_ATTRIBUTES tsa, LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES sa, int *server_handle );
int *server_thandle, int *server_phandle,
LPTHREAD_START_ROUTINE start_addr, LPVOID param );
extern THDB *THREAD_Current(void); extern THDB *THREAD_Current(void);
extern BOOL THREAD_IsWin16( THDB *thdb ); extern BOOL THREAD_IsWin16( THDB *thdb );
extern THDB *THREAD_IdToTHDB( DWORD id ); extern THDB *THREAD_IdToTHDB( DWORD id );
extern void THREAD_Start( THDB *thdb );
extern DWORD THREAD_TlsAlloc( THDB *thread ); extern DWORD THREAD_TlsAlloc( THDB *thread );
/* scheduler/sysdeps.c */ /* scheduler/sysdeps.c */

View file

@ -983,15 +983,6 @@ BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
CloseHandle( hFile ); CloseHandle( hFile );
} }
/* Get hTask from process and start the task */
if ( retv )
{
PDB *pdb = PROCESS_IdToPDB( lpProcessInfo->dwProcessId );
if (pdb) TASK_StartTask( pdb->task );
}
return retv; return retv;
} }

View file

@ -272,46 +272,42 @@ unsigned int CLIENT_WaitSimpleReply( void *reply, int len, int *passed_fd )
/*********************************************************************** /***********************************************************************
* CLIENT_NewThread * CLIENT_InitServer
* *
* Send a new thread request. * Start the server and create the initial socket pair.
*/ */
int CLIENT_NewThread( THDB *thdb, int CLIENT_InitServer(void)
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
int *thandle, int *phandle )
{ {
struct new_thread_request request;
struct new_thread_reply reply;
int fd[2]; int fd[2];
char buffer[16];
extern void create_initial_thread( int fd );
if (socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) == -1) if (socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) == -1)
{ {
SetLastError( ERROR_TOO_MANY_OPEN_FILES ); /* FIXME */ perror("socketpair");
return -1; exit(1);
} }
switch(fork())
request.pid = thdb->process->server_pid; {
request.suspend = (thdb->flags & CREATE_SUSPENDED)? TRUE : FALSE; case -1: /* error */
request.tinherit = (tsa && (tsa->nLength>=sizeof(*tsa)) && tsa->bInheritHandle); perror("fork");
request.pinherit = (psa && (psa->nLength>=sizeof(*psa)) && psa->bInheritHandle); exit(1);
CLIENT_SendRequest( REQ_NEW_THREAD, fd[1], 1, &request, sizeof(request) ); case 0: /* child */
if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) goto error; close( fd[0] );
thdb->server_tid = reply.tid; sprintf( buffer, "%d", fd[1] );
thdb->process->server_pid = reply.pid; /*#define EXEC_SERVER*/
if (thdb->socket != -1) close( thdb->socket ); #ifdef EXEC_SERVER
thdb->socket = fd[0]; execlp( "wineserver", "wineserver", buffer, NULL );
thdb->seq = 0; /* reset the sequence number for the new fd */ execl( "/usr/local/bin/wineserver", "wineserver", buffer, NULL );
fcntl( fd[0], F_SETFD, 1 ); /* set close on exec flag */ execl( "./server/wineserver", "wineserver", buffer, NULL );
#endif
if (thandle) *thandle = reply.thandle; create_initial_thread( fd[1] );
else if (reply.thandle != -1) CloseHandle( reply.thandle ); exit(0);
if (phandle) *phandle = reply.phandle; default: /* parent */
else if (reply.phandle != -1) CloseHandle( reply.phandle ); close( fd[1] );
return 0; break;
}
error: return fd[0];
close( fd[0] );
return -1;
} }
@ -322,16 +318,9 @@ int CLIENT_NewThread( THDB *thdb,
*/ */
int CLIENT_InitThread(void) int CLIENT_InitThread(void)
{ {
THDB *thdb = THREAD_Current();
struct init_thread_request init; struct init_thread_request init;
int len = strlen( thdb->process->env_db->cmd_line );
init.unix_pid = getpid(); init.unix_pid = getpid();
len = MIN( len, MAX_MSG_LENGTH - sizeof(init) ); CLIENT_SendRequest( REQ_INIT_THREAD, -1, 1, &init, sizeof(init) );
CLIENT_SendRequest( REQ_INIT_THREAD, -1, 2,
&init, sizeof(init),
thdb->process->env_db->cmd_line, len );
return CLIENT_WaitReply( NULL, NULL, 0 ); return CLIENT_WaitReply( NULL, NULL, 0 );
} }

View file

@ -178,6 +178,55 @@ static BOOL PROCESS_InheritEnvDB( PDB *pdb, LPCSTR cmd_line, LPCSTR env,
} }
/***********************************************************************
* PROCESS_CreateEnvDB
*
* Create the env DB for a newly started process.
*/
static BOOL PROCESS_CreateEnvDB(void)
{
struct init_process_request req;
struct init_process_reply reply;
STARTUPINFOA *startup;
ENVDB *env_db;
PDB *pdb = PROCESS_Current();
/* Retrieve startup info from the server */
req.dummy = 0;
CLIENT_SendRequest( REQ_INIT_PROCESS, -1, 1, &req, sizeof(req) );
if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
/* Allocate the env DB */
if (!(env_db = HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB) )))
return FALSE;
pdb->env_db = env_db;
InitializeCriticalSection( &env_db->section );
/* Allocate and fill the startup info */
if (!(startup = HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFOA) )))
return FALSE;
pdb->env_db->startup_info = startup;
startup->dwFlags = reply.start_flags;
pdb->env_db->hStdin = startup->hStdInput = reply.hstdin;
pdb->env_db->hStdout = startup->hStdOutput = reply.hstdout;
pdb->env_db->hStderr = startup->hStdError = reply.hstderr;
#if 0 /* FIXME */
/* Copy the parent environment */
if (!ENV_InheritEnvironment( pdb, env )) return FALSE;
/* Copy the command line */
if (!(pdb->env_db->cmd_line = HEAP_strdupA( pdb->heap, 0, cmd_line )))
return FALSE;
#endif
return TRUE;
}
/*********************************************************************** /***********************************************************************
* PROCESS_FreePDB * PROCESS_FreePDB
* *
@ -191,7 +240,6 @@ void PROCESS_FreePDB( PDB *pdb )
while (*pptr && (*pptr != pdb)) pptr = &(*pptr)->next; while (*pptr && (*pptr != pdb)) pptr = &(*pptr)->next;
if (*pptr) *pptr = pdb->next; if (*pptr) *pptr = pdb->next;
if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap ); if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap );
DeleteCriticalSection( &pdb->crit_section );
HeapFree( SystemHeap, 0, pdb ); HeapFree( SystemHeap, 0, pdb );
} }
@ -222,27 +270,16 @@ static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit )
} }
/***********************************************************************
* PROCESS_FinishCreatePDB
*
* Second part of CreatePDB
*/
static BOOL PROCESS_FinishCreatePDB( PDB *pdb )
{
InitializeCriticalSection( &pdb->crit_section );
/* Allocate the event */
if (!(pdb->load_done_evt = CreateEventA( NULL, TRUE, FALSE, NULL )))
return FALSE;
return TRUE;
}
/*********************************************************************** /***********************************************************************
* PROCESS_Init * PROCESS_Init
*/ */
BOOL PROCESS_Init(void) BOOL PROCESS_Init(void)
{ {
THDB *thdb; THDB *thdb;
int server_fd;
/* Start the server */
server_fd = CLIENT_InitServer();
/* Fill the initial process structure */ /* Fill the initial process structure */
initial_pdb.exit_code = 0x103; /* STILL_ACTIVE */ initial_pdb.exit_code = 0x103; /* STILL_ACTIVE */
@ -255,8 +292,8 @@ BOOL PROCESS_Init(void)
/* Initialize virtual memory management */ /* Initialize virtual memory management */
if (!VIRTUAL_Init()) return FALSE; if (!VIRTUAL_Init()) return FALSE;
/* Create the initial thread structure */ /* Create the initial thread structure and socket pair */
if (!(thdb = THREAD_CreateInitialThread( &initial_pdb ))) return FALSE; if (!(thdb = THREAD_CreateInitialThread( &initial_pdb, server_fd ))) return FALSE;
/* Remember TEB selector of initial process for emergency use */ /* Remember TEB selector of initial process for emergency use */
SYSLEVEL_EmergencyTeb = thdb->teb_sel; SYSLEVEL_EmergencyTeb = thdb->teb_sel;
@ -270,15 +307,82 @@ BOOL PROCESS_Init(void)
/* Initialize the first thread */ /* Initialize the first thread */
if (CLIENT_InitThread()) return FALSE; if (CLIENT_InitThread()) return FALSE;
if (!PROCESS_FinishCreatePDB( &initial_pdb )) return FALSE;
/* Create the SEGPTR heap */ /* Create the SEGPTR heap */
if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE; if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
/* Initialize the first process critical section */
InitializeCriticalSection( &initial_pdb.crit_section );
return TRUE; return TRUE;
} }
/***********************************************************************
* PROCESS_Start
*
* Startup routine of a new process. Called in the context of the new process.
*/
void PROCESS_Start(void)
{
DWORD size, commit;
UINT cmdShow = 0;
LPTHREAD_START_ROUTINE entry;
THDB *thdb = THREAD_Current();
PDB *pdb = thdb->process;
NE_MODULE *pModule = (NE_MODULE *)thdb->entry_arg; /* hack */
/* Initialize the critical section */
InitializeCriticalSection( &pdb->crit_section );
/* Create the heap */
size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapReserve;
commit = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapCommit;
if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
pdb->heap_list = pdb->heap;
/* Create the environment db */
if (!PROCESS_CreateEnvDB()) goto error;
#if 0
if (pdb->env_db->startup_info->dwFlags & STARTF_USESHOWWINDOW)
cmdShow = pdb->env_db->startup_info->wShowWindow;
if (!TASK_Create( thdb, pModule, 0, 0, cmdShow )) goto error;
#endif
/* Map system DLLs into this process (from initial process) */
/* FIXME: this is a hack */
pdb->modref_list = PROCESS_Initial()->modref_list;
/* Create 32-bit MODREF */
{
OFSTRUCT *ofs = (OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo);
if (!PE_CreateModule( pModule->module32, ofs, 0, FALSE )) goto error;
}
/* Initialize thread-local storage */
PE_InitTls( thdb );
if (PE_HEADER(pModule->module32)->OptionalHeader.Subsystem==IMAGE_SUBSYSTEM_WINDOWS_CUI)
AllocConsole();
/* Now call the entry point */
MODULE_InitializeDLLs( 0, DLL_PROCESS_ATTACH, (LPVOID)-1 );
entry = (LPTHREAD_START_ROUTINE)RVA_PTR(pModule->module32,
OptionalHeader.AddressOfEntryPoint);
TRACE(relay, "(entryproc=%p)\n", entry );
ExitProcess( entry(NULL) );
error:
ExitProcess(1);
}
/*********************************************************************** /***********************************************************************
* PROCESS_Create * PROCESS_Create
* *
@ -291,7 +395,9 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
PROCESS_INFORMATION *info ) PROCESS_INFORMATION *info )
{ {
DWORD size, commit; DWORD size, commit;
int server_thandle, server_phandle; int server_thandle;
struct new_process_request req;
struct new_process_reply reply;
UINT cmdShow = 0; UINT cmdShow = 0;
THDB *thdb = NULL; THDB *thdb = NULL;
PDB *parent = PROCESS_Current(); PDB *parent = PROCESS_Current();
@ -299,7 +405,33 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
if (!pdb) return NULL; if (!pdb) return NULL;
info->hThread = info->hProcess = INVALID_HANDLE_VALUE; info->hThread = info->hProcess = INVALID_HANDLE_VALUE;
if (!PROCESS_FinishCreatePDB( pdb )) goto error;
/* Create the process on the server side */
req.inherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
req.inherit_all = inherit;
req.start_flags = startup->dwFlags;
if (startup->dwFlags & STARTF_USESTDHANDLES)
{
req.hstdin = startup->hStdInput;
req.hstdout = startup->hStdOutput;
req.hstderr = startup->hStdError;
}
else
{
req.hstdin = GetStdHandle( STD_INPUT_HANDLE );
req.hstdout = GetStdHandle( STD_OUTPUT_HANDLE );
req.hstderr = GetStdHandle( STD_ERROR_HANDLE );
}
CLIENT_SendRequest( REQ_NEW_PROCESS, -1, 1, &req, sizeof(req) );
if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) goto error;
pdb->server_pid = reply.pid;
info->hProcess = reply.handle;
info->dwProcessId = (DWORD)pdb->server_pid;
/* Initialize the critical section */
InitializeCriticalSection( &pdb->crit_section );
/* Create the heap */ /* Create the heap */
@ -327,13 +459,9 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve; size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
else else
size = 0; size = 0;
if (!(thdb = THREAD_Create( pdb, 0L, size, hInstance == 0, if (!(thdb = THREAD_Create( pdb, 0L, size, hInstance == 0, tsa, &server_thandle )))
tsa, psa, &server_thandle, &server_phandle,
NULL, NULL )))
goto error; goto error;
info->hThread = server_thandle; info->hThread = server_thandle;
info->hProcess = server_phandle;
info->dwProcessId = (DWORD)pdb->server_pid;
info->dwThreadId = (DWORD)thdb->server_tid; info->dwThreadId = (DWORD)thdb->server_tid;
/* Duplicate the standard handles */ /* Duplicate the standard handles */
@ -362,6 +490,10 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
pdb->modref_list = PROCESS_Initial()->modref_list; pdb->modref_list = PROCESS_Initial()->modref_list;
/* Start the task */
TASK_StartTask( pdb->task );
return pdb; return pdb;
error: error:
@ -381,12 +513,13 @@ void WINAPI ExitProcess( DWORD status )
TDB *pTask = (TDB *)GlobalLock16( pdb->task ); TDB *pTask = (TDB *)GlobalLock16( pdb->task );
if ( pTask ) pTask->nEvents++; if ( pTask ) pTask->nEvents++;
MODULE_InitializeDLLs( 0, DLL_PROCESS_DETACH, NULL );
if ( pTask && pTask->thdb != THREAD_Current() ) if ( pTask && pTask->thdb != THREAD_Current() )
ExitThread( status ); TerminateProcess( GetCurrentProcess(), status );
/* FIXME: should kill all running threads of this process */ /* FIXME: should kill all running threads of this process */
pdb->exit_code = status; pdb->exit_code = status;
FreeConsole();
__RESTORE_ES; /* Necessary for Pietrek's showseh example program */ __RESTORE_ES; /* Necessary for Pietrek's showseh example program */
TASK_KillCurrentTask( status ); TASK_KillCurrentTask( status );

View file

@ -80,8 +80,14 @@ int *__h_errno_location()
*/ */
static void SYSDEPS_StartThread( THDB *thdb ) static void SYSDEPS_StartThread( THDB *thdb )
{ {
SET_FS( thdb->teb_sel ); struct init_thread_request init;
THREAD_Start( thdb );
SET_CUR_THREAD( thdb );
init.unix_pid = getpid();
CLIENT_SendRequest( REQ_INIT_THREAD, -1, 1, &init, sizeof(init) );
CLIENT_WaitReply( NULL, NULL, 0 );
thdb->startup();
_exit(0); /* should never get here */
} }
#endif /* USE_THREADS */ #endif /* USE_THREADS */

View file

@ -5,6 +5,7 @@
*/ */
#include <assert.h> #include <assert.h>
#include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
@ -94,8 +95,7 @@ THDB *THREAD_IdToTHDB( DWORD id )
* Initialization of a newly created THDB. * Initialization of a newly created THDB.
*/ */
static BOOL THREAD_InitTHDB( THDB *thdb, DWORD stack_size, BOOL alloc_stack16, static BOOL THREAD_InitTHDB( THDB *thdb, DWORD stack_size, BOOL alloc_stack16,
LPSECURITY_ATTRIBUTES tsa, LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES sa )
int *server_thandle, int *server_phandle )
{ {
DWORD old_prot; DWORD old_prot;
@ -136,11 +136,6 @@ static BOOL THREAD_InitTHDB( THDB *thdb, DWORD stack_size, BOOL alloc_stack16,
0x10000 - sizeof(STACK16FRAME) ); 0x10000 - sizeof(STACK16FRAME) );
} }
/* Create the thread socket */
if (CLIENT_NewThread( thdb, tsa, psa, server_thandle, server_phandle ))
goto error;
/* Create the thread event */ /* Create the thread event */
if (!(thdb->event = CreateEventA( NULL, FALSE, FALSE, NULL ))) goto error; if (!(thdb->event = CreateEventA( NULL, FALSE, FALSE, NULL ))) goto error;
@ -148,7 +143,6 @@ static BOOL THREAD_InitTHDB( THDB *thdb, DWORD stack_size, BOOL alloc_stack16,
return TRUE; return TRUE;
error: error:
if (thdb->socket != -1) close( thdb->socket );
if (thdb->event) CloseHandle( thdb->event ); if (thdb->event) CloseHandle( thdb->event );
if (thdb->teb.stack_sel) SELECTOR_FreeBlock( thdb->teb.stack_sel, 1 ); if (thdb->teb.stack_sel) SELECTOR_FreeBlock( thdb->teb.stack_sel, 1 );
if (thdb->stack_base) VirtualFree( thdb->stack_base, 0, MEM_RELEASE ); if (thdb->stack_base) VirtualFree( thdb->stack_base, 0, MEM_RELEASE );
@ -189,51 +183,16 @@ void THREAD_FreeTHDB( THDB *thdb )
* *
* Create the initial thread. * Create the initial thread.
*/ */
THDB *THREAD_CreateInitialThread( PDB *pdb ) THDB *THREAD_CreateInitialThread( PDB *pdb, int server_fd )
{ {
int fd[2];
char buffer[16];
extern void server_init( int fd );
extern void select_loop(void);
initial_thdb.process = pdb; initial_thdb.process = pdb;
initial_thdb.teb.except = (void *)-1; initial_thdb.teb.except = (void *)-1;
initial_thdb.teb.self = &initial_thdb.teb; initial_thdb.teb.self = &initial_thdb.teb;
initial_thdb.teb.flags = (pdb->flags & PDB32_WIN16_PROC)? 0 : TEBF_WIN32; initial_thdb.teb.flags = TEBF_WIN32;
initial_thdb.teb.tls_ptr = initial_thdb.tls_array; initial_thdb.teb.tls_ptr = initial_thdb.tls_array;
initial_thdb.teb.process = pdb; initial_thdb.teb.process = pdb;
initial_thdb.exit_code = 0x103; /* STILL_ACTIVE */ initial_thdb.exit_code = 0x103; /* STILL_ACTIVE */
initial_thdb.socket = -1; initial_thdb.socket = server_fd;
/* Start the server */
if (socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) == -1)
{
perror("socketpair");
exit(1);
}
switch(fork())
{
case -1: /* error */
perror("fork");
exit(1);
case 0: /* child */
close( fd[0] );
sprintf( buffer, "%d", fd[1] );
/*#define EXEC_SERVER*/
#ifdef EXEC_SERVER
execlp( "wineserver", "wineserver", buffer, NULL );
execl( "/usr/local/bin/wineserver", "wineserver", buffer, NULL );
execl( "./server/wineserver", "wineserver", buffer, NULL );
#endif
server_init( fd[1] );
select_loop();
exit(0);
default: /* parent */
initial_thdb.socket = fd[0];
close( fd[1] );
break;
}
/* Allocate the TEB selector (%fs register) */ /* Allocate the TEB selector (%fs register) */
@ -248,8 +207,7 @@ THDB *THREAD_CreateInitialThread( PDB *pdb )
/* Now proceed with normal initialization */ /* Now proceed with normal initialization */
if (!THREAD_InitTHDB( &initial_thdb, 0, TRUE, if (!THREAD_InitTHDB( &initial_thdb, 0, TRUE, NULL )) return NULL;
NULL, NULL, NULL, NULL )) return NULL;
return &initial_thdb; return &initial_thdb;
} }
@ -258,10 +216,12 @@ THDB *THREAD_CreateInitialThread( PDB *pdb )
* THREAD_Create * THREAD_Create
*/ */
THDB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16, THDB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16,
LPSECURITY_ATTRIBUTES tsa, LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES sa, int *server_handle )
int *server_thandle, int *server_phandle,
LPTHREAD_START_ROUTINE start_addr, LPVOID param )
{ {
struct new_thread_request request;
struct new_thread_reply reply = { NULL, -1 };
int fd[2];
THDB *thdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(THDB) ); THDB *thdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(THDB) );
if (!thdb) return NULL; if (!thdb) return NULL;
thdb->process = pdb; thdb->process = pdb;
@ -273,8 +233,6 @@ THDB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16
thdb->teb.process = pdb; thdb->teb.process = pdb;
thdb->exit_code = 0x103; /* STILL_ACTIVE */ thdb->exit_code = 0x103; /* STILL_ACTIVE */
thdb->flags = flags; thdb->flags = flags;
thdb->entry_point = start_addr;
thdb->entry_arg = param;
thdb->socket = -1; thdb->socket = -1;
/* Allocate the TEB selector (%fs register) */ /* Allocate the TEB selector (%fs register) */
@ -283,19 +241,39 @@ THDB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16
TRUE, FALSE ); TRUE, FALSE );
if (!thdb->teb_sel) goto error; if (!thdb->teb_sel) goto error;
/* Create the socket pair for server communication */
if (socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) == -1)
{
SetLastError( ERROR_TOO_MANY_OPEN_FILES ); /* FIXME */
goto error;
}
thdb->socket = fd[0];
fcntl( fd[0], F_SETFD, 1 ); /* set close on exec flag */
/* Create the thread on the server side */
request.pid = thdb->process->server_pid;
request.suspend = ((thdb->flags & CREATE_SUSPENDED) != 0);
request.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
CLIENT_SendRequest( REQ_NEW_THREAD, fd[1], 1, &request, sizeof(request) );
if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) goto error;
thdb->server_tid = reply.tid;
*server_handle = reply.handle;
/* Do the rest of the initialization */ /* Do the rest of the initialization */
if (!THREAD_InitTHDB( thdb, stack_size, alloc_stack16, if (!THREAD_InitTHDB( thdb, stack_size, alloc_stack16, sa )) goto error;
tsa, psa, server_thandle, server_phandle ))
goto error;
thdb->next = THREAD_First; thdb->next = THREAD_First;
THREAD_First = thdb; THREAD_First = thdb;
PE_InitTls( thdb ); PE_InitTls( thdb );
return thdb; return thdb;
error: error:
if (reply.handle != -1) CloseHandle( reply.handle );
if (thdb->teb_sel) SELECTOR_FreeBlock( thdb->teb_sel, 1 ); if (thdb->teb_sel) SELECTOR_FreeBlock( thdb->teb_sel, 1 );
HeapFree( SystemHeap, 0, thdb ); HeapFree( SystemHeap, 0, thdb );
if (thdb->socket != -1) close( thdb->socket );
return NULL; return NULL;
} }
@ -305,11 +283,10 @@ error:
* *
* Start execution of a newly created thread. Does not return. * Start execution of a newly created thread. Does not return.
*/ */
void THREAD_Start( THDB *thdb ) static void THREAD_Start(void)
{ {
THDB *thdb = THREAD_Current();
LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)thdb->entry_point; LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)thdb->entry_point;
assert( THREAD_Current() == thdb );
CLIENT_InitThread();
MODULE_InitializeDLLs( 0, DLL_THREAD_ATTACH, NULL ); MODULE_InitializeDLLs( 0, DLL_THREAD_ATTACH, NULL );
ExitThread( func( thdb->entry_arg ) ); ExitThread( func( thdb->entry_arg ) );
} }
@ -323,9 +300,11 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack,
DWORD flags, LPDWORD id ) DWORD flags, LPDWORD id )
{ {
int handle = -1; int handle = -1;
THDB *thread = THREAD_Create( PROCESS_Current(), flags, stack, THDB *thread = THREAD_Create( PROCESS_Current(), flags, stack, TRUE, sa, &handle );
TRUE, sa, NULL, &handle, NULL, start, param );
if (!thread) return INVALID_HANDLE_VALUE; if (!thread) return INVALID_HANDLE_VALUE;
thread->entry_point = start;
thread->entry_arg = param;
thread->startup = THREAD_Start;
if (SYSDEPS_SpawnThread( thread ) == -1) if (SYSDEPS_SpawnThread( thread ) == -1)
{ {
CloseHandle( handle ); CloseHandle( handle );