On Nov 9, 2010, at 5:48 PM, Edmond Ho wrote:

> To summarize, I use dup2() to "bind" stdout to my own NSPipe, and then add
> an NSNotification observer to listen for an
> NSFileHandleReadCompletionNotification on the NSPipe; the notification
> callback then reads the NSPipe. NSFileHandle readInBackgroundAndNotify is
> used to asynchronously read the data.
> 
> This approach works, for the most part -- when executed scripts print only a
> small amount of data to stdout, my app redirects the output to an NSTextView
> successfully. However, when executed scripts print a large amount of data to
> stdout, the app hangs.
> 
> I think the problem is that the pipe buffer is not being flushed/read when
> it's full; when the pipe is full, the script interpreter then is blocked
> because it's waiting for the pipe to empty so that it can write.

Yes, but do you understand why?  You're using the same thread to both write to 
the pipe and handle the data read from the pipe, but it can only be doing one 
at a time.

> I'm sure that what I want to do is possible -- after all, the Xcode debugger
> console has no problems displaying stdout when running the same script that
> hangs my app.

That's because Xcode is an independent process from the process executing the 
script.


> I guess my question is: How do I deal with a large amount of data that's
> printed to stdout in this situation? Is there some configuration I can use
> to change the buffering behavior (I've read elsewhere that stdout is
> block-buffered by default)? Is there a way to force NSFileHandle
> readInBackgroundAndNotify to read the pipe more frequently?

The size of the buffer doesn't matter, in the long run.  Nor does "buffering 
behavior".  And having NSFileHandle read more frequently, whatever that might 
mean, would only make the problem worse.

Think about it.  What does NSFileHandle do when it has read some data in the 
background?  It queues up a message for the main thread (or whatever thread you 
did the -readInBackgroundAndNotify from) to handle the data.  Until you issue 
another -readInBackgroundAndNotify, it doesn't read further.

Now, what is your main thread doing?  Well, it's writing to stdout.  It is 
definitely not prepared to handle the notification from NSFileHandle -- that 
is, it's not sitting idle in the run loop.  So, it has ceased asking 
NSFileHandle to read from the pipe.  So, eventually, the script is going to 
fill whatever buffer there is.

You have to arrange to execute the two things on independent threads of 
execution, or even processes.  That's the only way to avoid the problem.

Regards,
Ken

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to