Re: Problem with redirecting stdout
Re: Problem with redirecting stdout
- Subject: Re: Problem with redirecting stdout
- From: Ken Thomases <email@hidden>
- Date: Tue, 9 Nov 2010 23:06:17 -0600
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 (email@hidden)
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:
This email sent to email@hidden