2002-07-20 Dick Porter <dick@ximian.com>
authorDick Porter <dick@acm.org>
Sat, 20 Jul 2002 10:19:39 +0000 (10:19 -0000)
committerDick Porter <dick@acm.org>
Sat, 20 Jul 2002 10:19:39 +0000 (10:19 -0000)
* 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  <dick@ximian.com>

* 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

20 files changed:
mono/handles/hps.c
mono/io-layer/ChangeLog
mono/io-layer/Makefile.am
mono/io-layer/daemon.c
mono/io-layer/handles.c
mono/io-layer/io-private.h
mono/io-layer/io.c
mono/io-layer/io.h
mono/io-layer/processes.c
mono/io-layer/shared.c
mono/io-layer/threads.c
mono/io-layer/uglify.h
mono/io-layer/wapi-private.h
mono/metadata/ChangeLog
mono/metadata/file-io.c
mono/metadata/file-io.h
mono/metadata/icall.c
mono/metadata/process.c
mono/metadata/process.h
mono/tests/process2.cs [new file with mode: 0755]

index 541707cf8934628cf41e26afed138dcd79f9050b..53974fbeb5613ce004c0df34ae0d7f216622f501 100644 (file)
@@ -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));
+}
index ea54b033c7646c06263a92223460f08c629ec92f..f5923874f3ae70214dc7cf8859116b565765af5f 100644 (file)
@@ -1,3 +1,16 @@
+2002-07-20  Dick Porter  <dick@ximian.com>
+
+       * 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 <lupus@ximian.com>
 
index 9ec877d16fa04ab13a6c81f365d742fc5e794fca..b5abb224cc46b832c86b3b633ea6068613ebc4a9 100644 (file)
@@ -66,6 +66,7 @@ OTHER_SRC = \
        mutexes.h               \
        mutex-private.h         \
        mono-mutex.c            \
+       mono-mutex.h            \
        processes.c             \
        processes.h             \
        process-private.h       \
index 3f4a5ae5e19873b79e064e4e6c3f93fd6b6495b2..0d4f68ff2152cbadf663f4a7bc7b5fa227ede350 100644 (file)
@@ -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; i<getdtablesize (); i++) {
+                               close (i);
+                       }
                        
 #ifdef DEBUG
                        g_message (G_GNUC_PRETTY_FUNCTION
@@ -756,7 +762,7 @@ static void process_process_fork (guint32 idx,
 
 #ifdef DEBUG
                        {
-                               int i=0;
+                               i=0;
                                while(argv[i]!=NULL) {
                                        g_message ("arg %d: [%s]", i, argv[i]);
                                        i++;
index e1fd62e17dec0ea8addf3425a4f8ba2e0abbd960..862edf71343c2b034c309d0a63406dcb279eee97 100644 (file)
@@ -54,6 +54,7 @@ static struct _WapiHandleOps *handle_ops[WAPI_HANDLE_COUNT]={
        &_wapi_socket_ops,
        &_wapi_find_ops,
        &_wapi_process_ops,
+       &_wapi_pipe_ops,
 };
 
 static int daemon_sock;
@@ -275,10 +276,7 @@ gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type,
 
        shared_handle_data=&_wapi_shared_data->handles[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;
        }
 }
 
index dae015de8b8317b3ac5259041fb4b642cbd58649..59a35fb80f87946f22fb2a8dc60446bc1e6ce990 100644 (file)
@@ -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
index f0b620e4e6d461765380356460dbadfa32a74199..6984700e751505389fd77023b2650768be318989 100644 (file)
@@ -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);
+}
index 017e3f7acf04767782a8fcad3c3b9f410f068e39..a0c037d22ba3cbaf0f7d0568757dae8984b5eb74 100644 (file)
@@ -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_ */
index f861d403202a855382a2bb1a59dd41d9fd05fc5d..231e4d57276878b7227107fa9ca36194ec4cb23e 100644 (file)
@@ -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
                 */
index 7ed9e5c3999bc019d093045a62e445941e751d62..6e9ca42e4c499f6289bff58297345d14bceb9201 100644 (file)
@@ -49,6 +49,7 @@
 #include <sys/shm.h>
 #include <errno.h>
 #include <string.h>
+#include <fcntl.h>
 
 #include <mono/io-layer/wapi.h>
 #include <mono/io-layer/wapi-private.h>
@@ -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<getdtablesize (); i++) {
+                               close (i);
+                       }
+                       
                        /* _wapi_daemon_main() does not return */
                        _wapi_daemon_main ();
                        
index ca601bd4f5409db80ddc8bc516e533ec97d8a003..5b4aee439fe6180f5e5efacce087a21b9396682d 100644 (file)
@@ -65,7 +65,7 @@ static void thread_close_private (gpointer handle)
        struct _WapiHandlePrivate_thread *thread_handle;
        gboolean ok;
        
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_UNUSED, NULL,
+       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD, NULL,
                                (gpointer *)&thread_handle);
        if(ok==FALSE) {
                g_warning (G_GNUC_PRETTY_FUNCTION
index e762c016a7dc9b236ac38ae992406d681f77a7cd..96d219aa3762d3063b032e9659706b952298fec9 100644 (file)
@@ -37,6 +37,7 @@ typedef gpointer *LPHANDLE;
 typedef guint32 SOCKET;
 typedef gpointer HMODULE;
 
+typedef WapiSecurityAttributes SECURITY_ATTRIBUTES;
 typedef WapiSecurityAttributes *LPSECURITY_ATTRIBUTES;
 typedef WapiOverlapped *LPOVERLAPPED;
 typedef WapiThreadStart LPTHREAD_START_ROUTINE;
index f5a18bf27bd2e3c0a72905d3da26301aa802373e..525b8a3a6257de31ebe7ed789a188bebd1ee548a 100644 (file)
@@ -22,7 +22,7 @@
  *
  * If this ever reaches 255, we have problems :-(
  */
-#define _WAPI_HANDLE_VERSION 5
+#define _WAPI_HANDLE_VERSION 6
 
 typedef enum {
        WAPI_HANDLE_UNUSED=0,
@@ -35,6 +35,7 @@ typedef enum {
        WAPI_HANDLE_SOCKET,
        WAPI_HANDLE_FIND,
        WAPI_HANDLE_PROCESS,
+       WAPI_HANDLE_PIPE,
        WAPI_HANDLE_COUNT,
 } WapiHandleType;
 
index f10421729b8e92699504d31dd8667071af88d7a0..c8fc861f148763b0fd9dde2b1d852dd6353a95e8 100644 (file)
@@ -1,3 +1,12 @@
+2002-07-20  Dick Porter  <dick@ximian.com>
+
+       * process.h:
+       * process.c: Pass file handles to CreateProcess
+       
+       * icall.c:
+       * file-io.h:
+       * file-io.c: Implemented CreatePipe
+
 2002-07-19  Dietmar Maurer  <dietmar@ximian.com>
 
        * metadata.c (mono_get_param_info): set alignment for value types
index cad73f10311f00a550060d64b803a54b892b13c5..b36f192da10eef881fe05939af1788065beadf3e 100644 (file)
@@ -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 ()
 {
index ec6839ee7378f77c109b7f082dfba82e7a2b91ce..0efc3e2c55a7f32518a8dfcd8c24720ba7993ce3 100644 (file)
@@ -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);
 
index 3d3a3f64936235c7ce17fc952b9a7bd450e34d4b..2d2cde4c5c4e6c26ffcd36382d12a0c64e36ec0b 100644 (file)
@@ -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,
index 609c48586ee19926d8095c6a19e7034d478e0f65..fc5e17d44fb72e4238c8c2f8e6bd74de6161e3a7 100644 (file)
@@ -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);
index ceae229c81cc30f21da6add985d205f9094f5301..0bf88ee6f3ef6c2d0e43a2b717efeead84ff1584 100644 (file)
@@ -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 (executable)
index 0000000..25137e2
--- /dev/null
@@ -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();
+       }
+}
+