Skip to content

Instantly share code, notes, and snippets.

@patrickt
Created May 28, 2009 21:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save patrickt/119585 to your computer and use it in GitHub Desktop.
Save patrickt/119585 to your computer and use it in GitHub Desktop.
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