Created
May 28, 2009 21:22
-
-
Save patrickt/119585 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: io.c | |
=================================================================== | |
--- io.c (revision 1622) | |
+++ io.c (working copy) | |
@@ -498,9 +498,8 @@ | |
{ | |
off_t result; | |
- CFNumberRef pos = CFReadStreamCopyProperty(stream, | |
- kCFStreamPropertyFileCurrentOffset); | |
- CFNumberGetValue(pos, kCFNumberLongLongType, (void*)&result); | |
+ CFNumberRef pos = CFReadStreamCopyProperty(stream, kCFStreamPropertyFileCurrentOffset); | |
+ CFNumberGetValue(pos, kCFNumberSInt64Type, (void*)&result); | |
CFRelease(pos); | |
return result; | |
@@ -816,20 +815,12 @@ | |
return io; | |
} | |
-static inline long | |
+static long | |
rb_io_stream_read_internal(CFReadStreamRef readStream, UInt8 *buffer, long len) | |
{ | |
- long data_read = 0; | |
- | |
- while (data_read < len) { | |
- int code = CFReadStreamRead(readStream, &buffer[data_read], | |
- len - data_read); | |
+ long data_read = CFReadStreamRead(readStream, buffer, len); | |
- if (code == 0) { | |
- // EOF | |
- break; | |
- } | |
- else if (code == -1) { | |
+ if (data_read == -1) { | |
CFErrorRef er = CFReadStreamCopyError(readStream); | |
CFStringRef desc = CFErrorCopyDescription(er); | |
CFRelease(er); | |
@@ -839,9 +830,6 @@ | |
RSTRING_PTR(desc)); | |
} | |
- data_read += code; | |
- } | |
- | |
return data_read; | |
} | |
@@ -867,14 +855,8 @@ | |
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, | |
&buffer[data_read], len - data_read); | |
@@ -1138,11 +1120,12 @@ | |
{ | |
VALUE sep, limit; | |
sep = limit = Qnil; | |
- if (argc != 0) { | |
+ | |
rb_scan_args(argc, argv, "02", &sep, &limit); | |
- } | |
+ | |
rb_io_t *io_struct = ExtractIOStruct(io); | |
rb_io_assert_readable(io_struct); | |
+ | |
if (rb_io_eof(io, 0) == Qtrue) { | |
return Qnil; | |
} | |
@@ -1193,7 +1176,7 @@ | |
UInt8 *tmp_buf = alloca(seplen); | |
long data_read = 0; | |
- while (true) { | |
+ while (CFReadStreamHasBytesAvailable(io_struct->readStream)) { | |
if (rb_io_read_internal(io_struct, tmp_buf, seplen) != seplen) { | |
break; | |
} | |
@@ -1921,70 +1904,64 @@ | |
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); | |
- 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}; | |
+ io_struct->readStream = NULL; | |
+ io_struct->writeStream = 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] = {}; | |
- int fmode = convert_mode_string_to_fmode(mode); | |
+ pipe(comms); | |
- if (pipe(fd) < 0) { | |
+ 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 { | |
+ if (convert_mode_string_to_fmode(mode) != FMODE_WRITABLE) { | |
+ r = _CFReadStreamCreateFromFileDescriptor(NULL, comms[0]); | |
+ if (r != NULL) { | |
+ CFReadStreamOpen(r); | |
+ CFMakeCollectable(r); | |
+ GC_WB(&io_struct->readStream, r); | |
+ } | |
+ } | |
+ | |
+ if (convert_mode_string_to_fmode(mode) != FMODE_READABLE) { | |
+ w = _CFWriteStreamCreateFromFileDescriptor(NULL, comms[1]); | |
+ if (w != NULL) { | |
+ CFWriteStreamOpen(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); | |
- rb_sys_fail("pipe() failed."); | |
} | |
- // Confusingly enough, FMODE_WRITABLE means 'write-only' | |
- // and FMODE_READABLE means 'read-only'. | |
- if (fmode != FMODE_WRITABLE) { | |
- r = _CFReadStreamCreateFromFileDescriptor(NULL, fd[0]); | |
- if (r != NULL) { | |
- CFReadStreamOpen(r); | |
- GC_WB(&io_struct->readStream, r); | |
- CFMakeCollectable(r); | |
- } else { | |
- io_struct->readStream = NULL; | |
- } | |
- } | |
- if (fmode != FMODE_READABLE) { | |
- w = _CFWriteStreamCreateFromFileDescriptor(NULL, fd[0]); | |
- if (w != NULL) { | |
- CFWriteStreamOpen(w); | |
- GC_WB(&io_struct->writeStream, w); | |
- CFMakeCollectable(w); | |
- } else { | |
- io_struct->writeStream = NULL; | |
- } | |
- } | |
- | |
- 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; | |
+ | |
+ return io; | |
} | |
Index: rakelib/spec.rake | |
=================================================================== | |
--- rakelib/spec.rake (revision 1622) | |
+++ rakelib/spec.rake (working copy) | |
@@ -42,6 +42,7 @@ | |
io | |
inspect | |
initialize_copy | |
+ pipe | |
putc | |
readchar | |
sync |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment