From: Dick Porter Date: Sat, 20 Jul 2002 10:19:39 +0000 (-0000) Subject: 2002-07-20 Dick Porter X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=b083768ef977b84fd849c230b1649d77b508db42;p=mono.git 2002-07-20 Dick Porter * wapi-private.h: * io-private.h: * io.h: * io.c: * handles.c: Implemented pipe handles * handles.c: * daemon.c: Fixed bug in handle closing. * shared.c: * daemon.c: Forked processes now close all open file descriptors. 2002-07-20 Dick Porter * process.h: * process.c: Pass file handles to CreateProcess * icall.c: * file-io.h: * file-io.c: Implemented CreatePipe svn path=/trunk/mono/; revision=5960 --- diff --git a/mono/handles/hps.c b/mono/handles/hps.c index 541707cf893..53974fbeb56 100644 --- a/mono/handles/hps.c +++ b/mono/handles/hps.c @@ -17,6 +17,7 @@ static const guchar *event_details (struct _WapiHandleShared *handle); static const guchar *socket_details (struct _WapiHandleShared *handle); static const guchar *find_details (struct _WapiHandleShared *handle); static const guchar *process_details (struct _WapiHandleShared *handle); +static const guchar *pipe_details (struct _WapiHandleShared *handle); /* This depends on the ordering of the enum WapiHandleType in * io-layer/wapi-private.h @@ -32,6 +33,7 @@ static const char *typename[]={ "Socket", "Find", "Process", + "Pipe", "Error!!" }; @@ -48,6 +50,7 @@ static const guchar * (*details[])(struct _WapiHandleShared *)= socket_details, find_details, process_details, + pipe_details, unused_details, }; @@ -194,3 +197,8 @@ static const guchar *process_details (struct _WapiHandleShared *handle) return(buf); } + +static const guchar *pipe_details (struct _WapiHandleShared *handle) +{ + return(file_details (handle)); +} diff --git a/mono/io-layer/ChangeLog b/mono/io-layer/ChangeLog index ea54b033c76..f5923874f3a 100644 --- a/mono/io-layer/ChangeLog +++ b/mono/io-layer/ChangeLog @@ -1,3 +1,16 @@ +2002-07-20 Dick Porter + + * wapi-private.h: + * io-private.h: + * io.h: + * io.c: + * handles.c: Implemented pipe handles + + * handles.c: + * daemon.c: Fixed bug in handle closing. + + * shared.c: + * daemon.c: Forked processes now close all open file descriptors. Fri Jul 19 19:05:19 CEST 2002 Paolo Molaro diff --git a/mono/io-layer/Makefile.am b/mono/io-layer/Makefile.am index 9ec877d16fa..b5abb224cc4 100644 --- a/mono/io-layer/Makefile.am +++ b/mono/io-layer/Makefile.am @@ -66,6 +66,7 @@ OTHER_SRC = \ mutexes.h \ mutex-private.h \ mono-mutex.c \ + mono-mutex.h \ processes.c \ processes.h \ process-private.h \ diff --git a/mono/io-layer/daemon.c b/mono/io-layer/daemon.c index 3f4a5ae5e19..0d4f68ff215 100644 --- a/mono/io-layer/daemon.c +++ b/mono/io-layer/daemon.c @@ -238,7 +238,6 @@ static gboolean unref_handle (guint32 idx, guint32 handle) _wapi_handle_ops_close_shared (GUINT_TO_POINTER (handle)); - _wapi_shared_data->handles[handle].type=WAPI_HANDLE_UNUSED; mono_mutex_destroy (&_wapi_shared_data->handles[handle].signal_mutex); pthread_cond_destroy (&_wapi_shared_data->handles[handle].signal_cond); memset (&_wapi_shared_data->handles[handle].u, '\0', sizeof(_wapi_shared_data->handles[handle].u)); @@ -717,19 +716,26 @@ static void process_process_fork (guint32 idx, char **argv, *full_args; GError *gerr=NULL; gboolean ret; - + int i; + /* should we detach from the process group? * We're already running without a controlling * tty... */ - if(process_fork.inherit!=TRUE) { - /* Close all file descriptors */ - } /* Connect stdin, stdout and stderr */ dup2 (fds[0], 0); dup2 (fds[1], 1); dup2 (fds[2], 2); + + if(process_fork.inherit!=TRUE) { + /* FIXME: do something here */ + } + + /* Close all file descriptors */ + for(i=3; ihandles[idx]; - /* Allow WAPI_HANDLE_UNUSED to mean "dont care which - * type" - */ - if(shared_handle_data->type!=type && type != WAPI_HANDLE_UNUSED) { + if(shared_handle_data->type!=type) { return(FALSE); } @@ -407,13 +405,15 @@ void _wapi_handle_unref (gpointer handle) if(shared==FALSE) { _wapi_handle_ops_close_shared (handle); - _wapi_shared_data->handles[idx].type=WAPI_HANDLE_UNUSED; + mono_mutex_destroy (&_wapi_shared_data->handles[idx].signal_mutex); pthread_cond_destroy (&_wapi_shared_data->handles[idx].signal_cond); memset (&_wapi_shared_data->handles[idx].u, '\0', sizeof(_wapi_shared_data->handles[idx].u)); - } + } + _wapi_handle_ops_close_private (handle); + _wapi_shared_data->handles[idx].type=WAPI_HANDLE_UNUSED; } } diff --git a/mono/io-layer/io-private.h b/mono/io-layer/io-private.h index dae015de8b8..59a35fb80f8 100644 --- a/mono/io-layer/io-private.h +++ b/mono/io-layer/io-private.h @@ -17,8 +17,9 @@ extern struct _WapiHandleOps _wapi_file_ops; extern struct _WapiHandleOps _wapi_console_ops; extern struct _WapiHandleOps _wapi_find_ops; +extern struct _WapiHandleOps _wapi_pipe_ops; -/* Currently used for both FILE and CONSOLE handle types. This may +/* Currently used for both FILE, CONSOLE and PIPE handle types. This may * have to change in future. */ struct _WapiHandle_file diff --git a/mono/io-layer/io.c b/mono/io-layer/io.c index f0b620e4e6d..6984700e751 100644 --- a/mono/io-layer/io.c +++ b/mono/io-layer/io.c @@ -84,8 +84,27 @@ struct _WapiHandleOps _wapi_console_ops = { /* Find handle has no ops. */ struct _WapiHandleOps _wapi_find_ops = { - NULL, /* close */ - NULL, /* getfiletype */ + NULL, /* close_shared */ + NULL, /* close_private */ + NULL, /* signal */ + NULL, /* own */ + NULL, /* is_owned */ +}; + +static void pipe_close_shared (gpointer handle); +static void pipe_close_private (gpointer handle); +static WapiFileType pipe_getfiletype (void); +static gboolean pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, + guint32 *bytesread, WapiOverlapped *overlapped); +static gboolean pipe_write (gpointer handle, gconstpointer buffer, + guint32 numbytes, guint32 *byteswritten, + WapiOverlapped *overlapped); + +/* Pipe handles + */ +struct _WapiHandleOps _wapi_pipe_ops = { + pipe_close_shared, /* close_shared */ + pipe_close_private, /* close_private */ NULL, /* signal */ NULL, /* own */ NULL, /* is_owned */ @@ -95,7 +114,7 @@ static struct { /* File, console and pipe handles */ WapiFileType (*getfiletype)(void); - /* File and console handles */ + /* File, console and pipe handles */ gboolean (*readfile)(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread, WapiOverlapped *overlapped); @@ -145,6 +164,11 @@ static struct { {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, /* process */ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + /* pipe */ + {pipe_getfiletype, + pipe_read, + pipe_write, + NULL, NULL, NULL, NULL, NULL, NULL}, }; @@ -272,7 +296,7 @@ static void file_close_private (gpointer handle) struct _WapiHandlePrivate_file *file_private_handle; gboolean ok; - ok=_wapi_lookup_handle (handle, WAPI_HANDLE_UNUSED, NULL, + ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE, NULL, (gpointer *)&file_private_handle); if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION @@ -915,7 +939,7 @@ static void console_close_private (gpointer handle) struct _WapiHandlePrivate_file *console_private_handle; gboolean ok; - ok=_wapi_lookup_handle (handle, WAPI_HANDLE_UNUSED, NULL, + ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE, NULL, (gpointer *)&console_private_handle); if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION @@ -1034,6 +1058,167 @@ static gboolean console_write(gpointer handle, gconstpointer buffer, return(TRUE); } +static void pipe_close_shared (gpointer handle) +{ + struct _WapiHandle_file *pipe_handle; + gboolean ok; + + ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE, + (gpointer *)&pipe_handle, NULL); + if(ok==FALSE) { + g_warning (G_GNUC_PRETTY_FUNCTION + ": error looking up pipe handle %p", handle); + return; + } + +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION ": closing pipe handle %p", handle); +#endif + + if(pipe_handle->filename!=0) { + _wapi_handle_scratch_delete (pipe_handle->filename); + pipe_handle->filename=0; + } + if(pipe_handle->security_attributes!=0) { + _wapi_handle_scratch_delete (pipe_handle->security_attributes); + pipe_handle->security_attributes=0; + } +} + +static void pipe_close_private (gpointer handle) +{ + struct _WapiHandlePrivate_file *pipe_private_handle; + gboolean ok; + + ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE, NULL, + (gpointer *)&pipe_private_handle); + if(ok==FALSE) { + g_warning (G_GNUC_PRETTY_FUNCTION + ": error looking up pipe handle %p", handle); + return; + } + +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION + ": closing pipe handle %p with fd %d", handle, + pipe_private_handle->fd); +#endif + + close(pipe_private_handle->fd); +} + +static WapiFileType pipe_getfiletype(void) +{ + return(FILE_TYPE_PIPE); +} + +static gboolean pipe_read (gpointer handle, gpointer buffer, + guint32 numbytes, guint32 *bytesread, + WapiOverlapped *overlapped G_GNUC_UNUSED) +{ + struct _WapiHandle_file *pipe_handle; + struct _WapiHandlePrivate_file *pipe_private_handle; + gboolean ok; + int ret; + + ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE, + (gpointer *)&pipe_handle, + (gpointer *)&pipe_private_handle); + if(ok==FALSE) { + g_warning (G_GNUC_PRETTY_FUNCTION + ": error looking up pipe handle %p", handle); + return(FALSE); + } + + if(bytesread!=NULL) { + *bytesread=0; + } + + if(!(pipe_handle->fileaccess&GENERIC_READ) && + !(pipe_handle->fileaccess&GENERIC_ALL)) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, pipe_private_handle->fd, pipe_handle->fileaccess); +#endif + + return(FALSE); + } + +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION + ": reading up to %d bytes from pipe %p (fd %d)", numbytes, + handle, pipe_private_handle->fd); +#endif + + ret=read(pipe_private_handle->fd, buffer, numbytes); + if(ret==-1) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION + ": read of handle %p fd %d error: %s", handle, + pipe_private_handle->fd, strerror(errno)); +#endif + + return(FALSE); + } + +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": read %d bytes from pipe", ret); +#endif + + if(bytesread!=NULL) { + *bytesread=ret; + } + + return(TRUE); +} + +static gboolean pipe_write(gpointer handle, gconstpointer buffer, + guint32 numbytes, guint32 *byteswritten, + WapiOverlapped *overlapped G_GNUC_UNUSED) +{ + struct _WapiHandle_file *pipe_handle; + struct _WapiHandlePrivate_file *pipe_private_handle; + gboolean ok; + int ret; + + ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE, + (gpointer *)&pipe_handle, + (gpointer *)&pipe_private_handle); + if(ok==FALSE) { + g_warning (G_GNUC_PRETTY_FUNCTION + ": error looking up pipe handle %p", handle); + return(FALSE); + } + + if(byteswritten!=NULL) { + *byteswritten=0; + } + + if(!(pipe_handle->fileaccess&GENERIC_WRITE) && + !(pipe_handle->fileaccess&GENERIC_ALL)) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, pipe_private_handle->fd, pipe_handle->fileaccess); +#endif + + return(FALSE); + } + + ret=write(pipe_private_handle->fd, buffer, numbytes); + if(ret==-1) { +#ifdef DEBUG + g_message(G_GNUC_PRETTY_FUNCTION + ": write of handle %p fd %d error: %s", handle, + pipe_private_handle->fd, strerror(errno)); +#endif + + return(FALSE); + } + if(byteswritten!=NULL) { + *byteswritten=ret; + } + + return(TRUE); +} + static int convert_flags(guint32 fileaccess, guint32 createmode) { int flags=0; @@ -1737,7 +1922,7 @@ WapiFileType GetFileType(gpointer handle) WapiHandleType type=_wapi_handle_type (handle); if(io_ops[type].getfiletype==NULL) { - return(FALSE); + return(FILE_TYPE_UNKNOWN); } return(io_ops[type].getfiletype ()); @@ -2479,10 +2664,15 @@ int _wapi_file_handle_to_fd (gpointer handle) ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE, NULL, (gpointer *)&file_private_handle); if(ok==FALSE) { + ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE, NULL, + (gpointer *)&file_private_handle); + if(ok==FALSE) { #ifdef DEBUG - g_message (G_GNUC_PRETTY_FUNCTION ": returning -1"); + g_message (G_GNUC_PRETTY_FUNCTION + ": returning -1"); #endif - return(-1); + return(-1); + } } } @@ -2493,3 +2683,106 @@ int _wapi_file_handle_to_fd (gpointer handle) return(file_private_handle->fd); } + +gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe, + WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 size) +{ + struct _WapiHandle_file *pipe_read_handle; + struct _WapiHandle_file *pipe_write_handle; + struct _WapiHandlePrivate_file *pipe_read_private_handle; + struct _WapiHandlePrivate_file *pipe_write_private_handle; + gpointer read_handle; + gpointer write_handle; + gboolean ok; + int filedes[2]; + int ret; + + mono_once (&io_ops_once, io_ops_init); + +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": Creating pipe"); +#endif + + ret=pipe (filedes); + if(ret==-1) { +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": Error creating pipe: %s", + strerror (errno)); +#endif + + _wapi_set_last_error_from_errno (); + return(FALSE); + } + + /* filedes[0] is open for reading, filedes[1] for writing */ + + read_handle=_wapi_handle_new (WAPI_HANDLE_PIPE); + if(read_handle==_WAPI_HANDLE_INVALID) { + g_warning (G_GNUC_PRETTY_FUNCTION + ": error creating pipe read handle"); + close (filedes[0]); + close (filedes[1]); + return(FALSE); + } + + _wapi_handle_lock_handle (read_handle); + + ok=_wapi_lookup_handle (read_handle, WAPI_HANDLE_PIPE, + (gpointer *)&pipe_read_handle, + (gpointer *)&pipe_read_private_handle); + if(ok==FALSE) { + g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", read_handle); + _wapi_handle_unlock_handle (read_handle); + close (filedes[0]); + close (filedes[1]); + return(FALSE); + } + + write_handle=_wapi_handle_new (WAPI_HANDLE_PIPE); + if(write_handle==_WAPI_HANDLE_INVALID) { + g_warning (G_GNUC_PRETTY_FUNCTION + ": error creating pipe write handle"); + _wapi_handle_unlock_handle (read_handle); + _wapi_handle_unref (read_handle); + + close (filedes[0]); + close (filedes[1]); + return(FALSE); + } + + _wapi_handle_lock_handle (write_handle); + + ok=_wapi_lookup_handle (write_handle, WAPI_HANDLE_PIPE, + (gpointer *)&pipe_write_handle, + (gpointer *)&pipe_write_private_handle); + if(ok==FALSE) { + g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", read_handle); + _wapi_handle_unlock_handle (read_handle); + _wapi_handle_unref (read_handle); + _wapi_handle_unlock_handle (write_handle); + close (filedes[0]); + close (filedes[1]); + return(FALSE); + } + + pipe_read_private_handle->fd=filedes[0]; + pipe_read_handle->fileaccess=GENERIC_READ; + + *readpipe=read_handle; + + pipe_write_private_handle->fd=filedes[1]; + pipe_write_handle->fileaccess=GENERIC_WRITE; + + *writepipe=write_handle; + + _wapi_handle_unlock_handle (read_handle); + _wapi_handle_unlock_handle (write_handle); + +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION + ": Returning pipe: read handle %p, write handle %p", + read_handle, write_handle); +#endif + + return(TRUE); +} diff --git a/mono/io-layer/io.h b/mono/io-layer/io.h index 017e3f7acf0..a0c037d22ba 100644 --- a/mono/io-layer/io.h +++ b/mono/io-layer/io.h @@ -184,5 +184,7 @@ extern gboolean GetFileAttributesEx (const gunichar2 *name, extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs); extern guint32 GetCurrentDirectory (guint32 length, gunichar2 *buffer); extern gboolean SetCurrentDirectory (const gunichar2 *path); +extern gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe, + WapiSecurityAttributes *security, guint32 size); #endif /* _WAPI_IO_H_ */ diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index f861d403202..231e4d57276 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -227,6 +227,9 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline, * marks into account */ + /* FIXME: move the contents of args down when token + * has been set (otherwise argv[0] is duplicated) + */ /* Assume the opening quote will always be the first * character */ diff --git a/mono/io-layer/shared.c b/mono/io-layer/shared.c index 7ed9e5c3999..6e9ca42e4c4 100644 --- a/mono/io-layer/shared.c +++ b/mono/io-layer/shared.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -148,6 +149,8 @@ try_again: _wapi_shm_destroy (); exit (-1); } else if (pid==0) { + int i; + /* child */ setsid (); @@ -158,6 +161,13 @@ try_again: * informative */ + /* Start the daemon with a clean sheet of file + * descriptors + */ + for(i=3; i + + * process.h: + * process.c: Pass file handles to CreateProcess + + * icall.c: + * file-io.h: + * file-io.c: Implemented CreatePipe + 2002-07-19 Dietmar Maurer * metadata.c (mono_get_param_info): set alignment for value types diff --git a/mono/metadata/file-io.c b/mono/metadata/file-io.c index cad73f10311..b36f192da10 100644 --- a/mono/metadata/file-io.c +++ b/mono/metadata/file-io.c @@ -528,6 +528,26 @@ ves_icall_System_IO_MonoIO_get_ConsoleError () return GetStdHandle (STD_ERROR_HANDLE); } +MonoBoolean +ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, + HANDLE *write_handle) +{ + SECURITY_ATTRIBUTES attr; + gboolean ret; + + attr.nLength=sizeof(SECURITY_ATTRIBUTES); + attr.bInheritHandle=TRUE; + attr.lpSecurityDescriptor=NULL; + + ret=CreatePipe (read_handle, write_handle, &attr, 0); + if(ret==FALSE) { + /* FIXME: throw an exception? */ + return(FALSE); + } + + return(TRUE); +} + gunichar2 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar () { diff --git a/mono/metadata/file-io.h b/mono/metadata/file-io.h index ec6839ee737..0efc3e2c55a 100644 --- a/mono/metadata/file-io.h +++ b/mono/metadata/file-io.h @@ -139,6 +139,10 @@ ves_icall_System_IO_MonoIO_get_ConsoleInput (void); extern HANDLE ves_icall_System_IO_MonoIO_get_ConsoleError (void); +extern MonoBoolean +ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, + HANDLE *write_handle); + extern gunichar2 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar (void); diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 3d3a3f64936..2d2cde4c5c4 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -2653,6 +2653,7 @@ static gconstpointer icall_map [] = { "System.IO.MonoIO::get_ConsoleOutput", ves_icall_System_IO_MonoIO_get_ConsoleOutput, "System.IO.MonoIO::get_ConsoleInput", ves_icall_System_IO_MonoIO_get_ConsoleInput, "System.IO.MonoIO::get_ConsoleError", ves_icall_System_IO_MonoIO_get_ConsoleError, + "System.IO.MonoIO::CreatePipe(intptr&,intptr&)", ves_icall_System_IO_MonoIO_CreatePipe, "System.IO.MonoIO::get_VolumeSeparatorChar", ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar, "System.IO.MonoIO::get_DirectorySeparatorChar", ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar, "System.IO.MonoIO::get_AltDirectorySeparatorChar", ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar, @@ -2730,7 +2731,7 @@ static gconstpointer icall_map [] = { "System.Diagnostics.Process::GetPid_internal()", ves_icall_System_Diagnostics_Process_GetPid_internal, "System.Diagnostics.Process::Process_free_internal(intptr)", ves_icall_System_Diagnostics_Process_Process_free_internal, "System.Diagnostics.Process::GetModules_internal()", ves_icall_System_Diagnostics_Process_GetModules_internal, - "System.Diagnostics.Process::Start_internal(string,string,ProcInfo&)", ves_icall_System_Diagnostics_Process_Start_internal, + "System.Diagnostics.Process::Start_internal(string,string,intptr,intptr,intptr,ProcInfo&)", ves_icall_System_Diagnostics_Process_Start_internal, "System.Diagnostics.Process::WaitForExit_internal(intptr,int)", ves_icall_System_Diagnostics_Process_WaitForExit_internal, "System.Diagnostics.Process::ExitTime_internal(intptr)", ves_icall_System_Diagnostics_Process_ExitTime_internal, "System.Diagnostics.Process::StartTime_internal(intptr)", ves_icall_System_Diagnostics_Process_StartTime_internal, diff --git a/mono/metadata/process.c b/mono/metadata/process.c index 609c48586ee..fc5e17d44fb 100644 --- a/mono/metadata/process.c +++ b/mono/metadata/process.c @@ -655,7 +655,7 @@ void ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoO mono_image_close (image); } -MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *filename, MonoString *args, MonoProcInfo *process_info) +MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *filename, MonoString *args, HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoProcInfo *process_info) { gboolean ret; gunichar2 *utf16_filename; @@ -666,6 +666,12 @@ MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *fil utf16_filename=mono_string_to_utf16 (filename); utf16_args=mono_string_to_utf16 (args); + startinfo.cb=sizeof(STARTUPINFO); + startinfo.dwFlags=STARTF_USESTDHANDLES; + startinfo.hStdInput=stdin_handle; + startinfo.hStdOutput=stdout_handle; + startinfo.hStdError=stderr_handle; + ret=CreateProcess (utf16_filename, utf16_args, NULL, NULL, TRUE, CREATE_UNICODE_ENVIRONMENT, NULL, NULL, &startinfo, &procinfo); g_free (utf16_filename); diff --git a/mono/metadata/process.h b/mono/metadata/process.h index ceae229c81c..0bf88ee6f3e 100644 --- a/mono/metadata/process.h +++ b/mono/metadata/process.h @@ -29,7 +29,7 @@ extern guint32 ves_icall_System_Diagnostics_Process_GetPid_internal (void); extern void ves_icall_System_Diagnostics_Process_Process_free_internal (MonoObject *this, HANDLE process); extern MonoArray *ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this); extern void ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this, MonoString *filename); -extern MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *filename, MonoString *args, MonoProcInfo *process_handle); +extern MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *filename, MonoString *args, HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoProcInfo *process_handle); extern MonoBoolean ves_icall_System_Diagnostics_Process_WaitForExit_internal (MonoObject *this, HANDLE process, gint32 ms); extern gint64 ves_icall_System_Diagnostics_Process_ExitTime_internal (HANDLE process); extern gint64 ves_icall_System_Diagnostics_Process_StartTime_internal (HANDLE process); diff --git a/mono/tests/process2.cs b/mono/tests/process2.cs new file mode 100755 index 00000000000..25137e2762c --- /dev/null +++ b/mono/tests/process2.cs @@ -0,0 +1,47 @@ +using System; +using System.Diagnostics; +using System.Threading; + +class Modules { + static void Run() { + Process proc = new Process(); + bool ret; + + proc.StartInfo.FileName="wibble-redir"; + proc.StartInfo.Arguments="arg1 arg2\targ3 \"arg4a arg4b\""; + proc.StartInfo.UseShellExecute=false; + proc.StartInfo.RedirectStandardInput=true; + ret=proc.Start(); + + Console.WriteLine("Start returns " + ret); + Console.WriteLine("Process is " + proc.ToString()); + Console.WriteLine("Pid is " + proc.Id); + Console.WriteLine("Handle is " + proc.Handle); + Console.WriteLine("HandleCount is " + proc.HandleCount); + + Console.WriteLine("Writing [foo bar]"); + proc.StandardInput.WriteLine("foo bar"); + + System.Threading.Thread.Sleep(1000); + + Console.WriteLine("Writing [wibble wobble]"); + proc.StandardInput.WriteLine("wibble wobble"); + + System.Threading.Thread.Sleep(1000); + + Console.WriteLine("Closing stdin"); + proc.StandardInput.Close(); + + Console.WriteLine("Waiting for exit..."); + proc.WaitForExit(); + Console.WriteLine("Wait returned"); + Console.WriteLine("Exit code is " + proc.ExitCode); + Console.WriteLine("Process started at " + proc.StartTime); + Console.WriteLine("Process ended at " + proc.ExitTime); + } + + static void Main() { + Run(); + } +} +