[macruby-changes] [1606] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Tue May 26 19:50:36 PDT 2009


Revision: 1606
          http://trac.macosforge.org/projects/ruby/changeset/1606
Author:   lsansonetti at apple.com
Date:     2009-05-26 19:50:36 -0700 (Tue, 26 May 2009)
Log Message:
-----------
reverted r1604 because it introduces a regression (hang) that breaks rubyspecs

Modified Paths:
--------------
    MacRuby/branches/experimental/include/ruby/io.h
    MacRuby/branches/experimental/io.c

Modified: MacRuby/branches/experimental/include/ruby/io.h
===================================================================
--- MacRuby/branches/experimental/include/ruby/io.h	2009-05-27 02:40:42 UTC (rev 1605)
+++ MacRuby/branches/experimental/include/ruby/io.h	2009-05-27 02:50:36 UTC (rev 1606)
@@ -29,7 +29,9 @@
     CFReadStreamRef readStream;
     CFWriteStreamRef writeStream;
     
+    // The Unixy low-level file handles.
     int fd; // You can expect this to be what the above CFStreams point to.
+    int pipe;
 
     // Additional information.
     CFStringRef path;

Modified: MacRuby/branches/experimental/io.c
===================================================================
--- MacRuby/branches/experimental/io.c	2009-05-27 02:40:42 UTC (rev 1605)
+++ MacRuby/branches/experimental/io.c	2009-05-27 02:50:36 UTC (rev 1606)
@@ -25,12 +25,15 @@
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <sys/syscall.h>
-#include <sys/socket.h>
 #include <spawn.h>
 #include <crt_externs.h>
 
 extern void Init_File(void);
 
+#if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
+# error off_t is bigger than long, but you have no long long...
+#endif
+
 VALUE rb_cIO;
 VALUE rb_eEOFError;
 VALUE rb_eIOError;
@@ -48,6 +51,8 @@
 
 static ID id_write, id_read, id_getc, id_flush, id_encode, id_readpartial;
 
+struct timeval rb_time_interval(VALUE);
+
 struct argf {
     VALUE filename, current_file;
     int gets_lineno;
@@ -62,6 +67,15 @@
 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
 #define ARGF argf_of(argf)
 
+// static int
+// is_socket(int fd, const char *path)
+// {
+//     struct stat sbuf;
+//     if (fstat(fd, &sbuf) < 0)
+//         rb_sys_fail(path);
+//     return S_ISSOCK(sbuf.st_mode);
+// }
+
 static int
 convert_mode_string_to_fmode(VALUE rstr)
 {
@@ -311,9 +325,12 @@
 
     // TODO: Eventually make the ungetc_buf a ByteString
     io_struct->fd = fd;
+	io_struct->pipe = -1;
     io_struct->ungetc_buf = NULL;
     io_struct->ungetc_buf_len = 0;
     io_struct->ungetc_buf_pos = 0;
+
+	
     
     io_struct->sync = mode & FMODE_SYNC;
 }
@@ -327,6 +344,10 @@
     if (close_write && io_struct->writeStream != NULL) {
 	CFWriteStreamClose(io_struct->writeStream);
     }
+	if(io_struct->pipe != -1) {
+		write(io_struct->pipe, "\0", 1);
+		close(io_struct->pipe);
+	}
 	rb_last_status_set(0, io_struct->pid);
 	io_struct->pid = -1;
 }
@@ -659,7 +680,8 @@
 {
     rb_io_t *io_struct = ExtractIOStruct(io);
     rb_io_assert_readable(io_struct);
-    return CONDITION_TO_BOOLEAN(CFReadStreamGetStatus(io_struct->readStream) == kCFStreamStatusAtEnd);
+    return CONDITION_TO_BOOLEAN(
+	    CFReadStreamGetStatus(io_struct->readStream) == kCFStreamStatusAtEnd);
 }
 
 /*
@@ -867,6 +889,13 @@
 	    return data_read;
 	}
     }
+	
+    if (io_struct->pipe != -1) {
+	int status;
+	waitpid(io_struct->pid, &status, 0);
+	close(io_struct->pipe);
+	io_struct->pipe = -1;
+    }
 
     // Read from the stream.
     data_read += rb_io_stream_read_internal(io_struct->readStream,
@@ -1752,7 +1781,6 @@
 static VALUE
 rb_io_close_read(VALUE io, SEL sel)
 {
-	rb_io_assert_readable(ExtractIOStruct(io));
     io_close(io, true, false);
     return Qnil;
 }
@@ -1898,76 +1926,94 @@
  *     <foo>bar;zot;
  */
 
+// just set errno, you bastards
+#define rb_sys_fail_unless(action, msg) do { \
+	errno = action;\
+	if (errno != 0) { \
+		rb_sys_fail(msg);\
+	}\
+} while(0)
+
+
 VALUE 
 io_from_spawning_new_process(VALUE prog, VALUE mode)
 {
-	// Allocate space for a new IO struct.
 	VALUE io = io_alloc(rb_cIO, 0);
     rb_io_t *io_struct = ExtractIOStruct(io);
-	io_struct->readStream = NULL;
-	io_struct->writeStream = NULL;
+	CFReadStreamRef r = NULL;
+    CFWriteStreamRef w = NULL;
+	pid_t pid;
+	int fd[2];
+	// TODO: Split the process_name up into char* components?
+	char *spawnedArgs[] = {(char*)_PATH_BSHELL, "-c", (char*)RSTRING_PTR(prog), NULL};
 	posix_spawn_file_actions_t actions;
-
-	// Streams for reading and writing.
-	CFReadStreamRef r;
-    CFWriteStreamRef w;
-
-	// Required variables for pipe() and posix_spawn().
-	pid_t pid;
-	int comms[2] = {};
 	
-	socketpair(PF_LOCAL, SOCK_STREAM, 0, comms);
+	int fmode = convert_mode_string_to_fmode(mode);
+	int readable = ((fmode & FMODE_READABLE) || (fmode & FMODE_READWRITE));
+	int writable = ((fmode & FMODE_WRITABLE) || (fmode & FMODE_READWRITE));
+	assert(readable || writable);
 	
-	posix_spawn_file_actions_init(&actions);
-	posix_spawn_file_actions_adddup2(&actions, comms[1], STDOUT_FILENO);
-	posix_spawn_file_actions_adddup2(&actions, STDOUT_FILENO, STDERR_FILENO);
-	posix_spawn_file_actions_addclose(&actions, comms[0]);
-	posix_spawn_file_actions_addclose(&actions, comms[1]);
-	
-	char *spawnedArgs[] = {(char*)_PATH_BSHELL, "-c", (char*)RSTRING_PTR(prog), NULL};
-	int error = posix_spawn(&pid, spawnedArgs[0], &actions, NULL, spawnedArgs, *(_NSGetEnviron()));
-
-	if (error != 0) {
-		close(comms[0]);
-		close(comms[1]);
-		rb_bug("posix_spawn failed.");
-	} 
-	else {
-		r = _CFReadStreamCreateFromFileDescriptor(NULL, comms[0]);
+	if (pipe(fd) < 0) {
+		posix_spawn_file_actions_destroy(&actions);
+		rb_sys_fail("pipe() failed.");
+	}
+	if (readable) {
+		r = _CFReadStreamCreateFromFileDescriptor(NULL, fd[0]);
 		if (r != NULL) {
-			CFReadStreamOpen(r); 
+			CFReadStreamOpen(r);
+			GC_WB(&io_struct->readStream, r);
 			CFMakeCollectable(r);
-			GC_WB(&io_struct->readStream, r);
+		} else {
+			io_struct->readStream = NULL;
 		}
-
-		w = _CFWriteStreamCreateFromFileDescriptor(NULL, comms[1]);
+    }
+	if (writable) {
+		w = _CFWriteStreamCreateFromFileDescriptor(NULL, fd[0]);
 		if (w != NULL) {
 			CFWriteStreamOpen(w);
+			GC_WB(&io_struct->writeStream, w);
 			CFMakeCollectable(w);
-			GC_WB(&io_struct->writeStream, w);
-		}
-		io_struct->fd = comms[0];
-		io_struct->pid = pid;
-		io_struct->ungetc_buf = NULL;
-		io_struct->ungetc_buf_len = 0;
-		io_struct->ungetc_buf_pos = 0;
-		posix_spawn_file_actions_destroy(&actions);
+    	} else {
+			io_struct->writeStream = NULL;
+    	}
 	}
-
-	return io;
+	
+	rb_sys_fail_unless(posix_spawn_file_actions_init(&actions), "could not init file actions");
+	rb_sys_fail_unless(posix_spawn_file_actions_adddup2(&actions, fd[1], STDOUT_FILENO), "could not add dup2() to stdout");
+	rb_sys_fail_unless(posix_spawn_file_actions_addclose(&actions, fd[1]), "could not add a close() to stdout");
+	
+	errno = posix_spawn(&pid, spawnedArgs[0], &actions, NULL, spawnedArgs, *(_NSGetEnviron()));
+	if(errno != 0) {
+		int err = errno;
+		close(fd[0]);
+		close(fd[1]);
+		errno = err;
+		rb_sys_fail("posix_spawn failed.");
+	}
+	posix_spawn_file_actions_destroy(&actions);
+	
+    // TODO: Eventually make the ungetc_buf a ByteString
+    io_struct->fd = fd[0];
+	io_struct->pipe = fd[1];
+    io_struct->ungetc_buf = NULL;
+    io_struct->ungetc_buf_len = 0;
+    io_struct->ungetc_buf_pos = 0;
+	io_struct->pid = pid;
+    io_struct->sync = mode & FMODE_SYNC;
+	
+    rb_objc_keep_for_exit_finalize((VALUE)io);
+    return io;
 }
 
+
 static VALUE
 rb_io_s_popen(VALUE klass, SEL sel, int argc, VALUE *argv)
 {
     VALUE process_name, mode;
-
     rb_scan_args(argc, argv, "11", &process_name, &mode);
 	if (NIL_P(mode)) mode = (VALUE)CFSTR("r");
-	
 	StringValue(process_name);
 	VALUE io = io_from_spawning_new_process(process_name, mode);
-	
 	if (rb_block_given_p()) {
         VALUE ret = rb_vm_yield(1, &io);
         rb_io_close_m(io, 0);
@@ -2005,6 +2051,23 @@
 
 /*
  *  call-seq:
+ *     IO.sysopen(path, [mode, [perm]])  => fixnum
+ *
+ *  Opens the given path, returning the underlying file descriptor as a
+ *  <code>Fixnum</code>.
+ *
+ *     IO.sysopen("testfile")   #=> 3
+ *
+ */
+
+static VALUE
+rb_io_s_sysopen(VALUE klass, SEL sel, int argc, VALUE *argv)
+{
+rb_notimplement();
+}
+
+/*
+ *  call-seq:
  *     open(path [, mode_enc [, perm]] )                => io or nil
  *     open(path [, mode_enc [, perm]] ) {|io| block }  => obj
  *
@@ -2145,29 +2208,8 @@
 	return io;
 }
 
-
 /*
  *  call-seq:
- *     IO.sysopen(path, [mode, [perm]])  => fixnum
- *
- *  Opens the given path, returning the underlying file descriptor as a
- *  <code>Fixnum</code>.
- *
- *     IO.sysopen("testfile")   #=> 3
- *
- */
-
-static VALUE
-rb_io_s_sysopen(VALUE klass, SEL sel, int argc, VALUE *argv)
-{
-    VALUE io = rb_class_new_instance(argc, argv, rb_cFile);
-    io = rb_file_open(io, argc, argv);
-	return INT2FIX(ExtractIOStruct(io)->fd);
-}
-
-
-/*
- *  call-seq:
  *     ios.reopen(other_IO)         => ios
  *     ios.reopen(path, mode_str)   => ios
  *
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090526/eb6ea7f9/attachment.html>


More information about the macruby-changes mailing list