[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