Re: Using /dev/stdout in a sandboxed app

Sandor Szatmari

I think you would pass

-progress pipe:1 will write out to stdout, 


pipe:2 to stderr.

Then just read from the pipe you associate.

I haven’t tried it myself, google told me to do it.

It might mess up your parsing if other messages are interspersed in the progress messages, but hopefully you can distinguish between the two types of information.  


On Jul 9, 2019, at 02:42, Graham Cox <graham@...> wrote:

Hi Chris,

actually I think I am doing that.

it’s a while since i put this code together, and exactly what the arguments are is not so clear now. I set the NSTask.standardOutput to an NSPipe, and I have a callback block that deals with that.

However, I’m also passing the -progress argument to ffmpeg as /dev/stdout. Now ffmpeg has a million options, and the documentation is rather terse. All it says for the -progress option is:

<Screen Shot 2019-07-09 at 4.26.06 pm.png>

I pass /dev/stdout as the url argument because what else could it be? My assumption was that NSTask’s standardOutput basically read from there, it was just a convenient place to hook in. The fact it worked led me never to further question that until now. If you don’t pass the -progress parameter, ffmpeg doesn’t send anything.

So the problem isn’t so much the NSTask, but what to pass as a url parameter to the -progress option.

The gist of the code is (with irrelevant stuff cut for clarity and brevity)

NSPipe* progressPipe = [NSPipe pipe];

progressPipe.fileHandleForReading.readabilityHandler = ^(NSFileHandle* handle )
// parse progress reports to update UI with certain info

// create the FFMPEG task:

NSString* execPath = [[[self class] ffMPEGURL] path];
NSArray* codecArgs = [[[self class] ffMPEGCodecForOption:self.format] componentsSeparatedByString:@" "];

if( codecArgs.count > 0 )
if( self.outputFileURL == nil )
[self requestDelegateCreatesFile];

NSAssert( self.outputFileURL, @"unable to proceed - no output file");

NSMutableArray* args = [NSMutableArray array];

[args addObjectsFromArray:@[@"-loglevel", @"error", @"-i", url.absoluteString]];
[args addObjectsFromArray:codecArgs];
[args addObjectsFromArray:@[@"-progress", @"/dev/stdout", self.outputFileURL.path]];  /<——————————————— set up -progress option

XVLOG(@"ffmpeg arguments: %@", args);

NSTask* theTask = [[NSTask alloc] init];

NSAssert( theTask, @"unable to create NSTask for ffmpeg subprocess");

theTask.launchPath = execPath;
theTask.arguments = args;
theTask.standardOutput = progressPipe;
theTask.qualityOfService = NSQualityOfServiceUserInitiated;

theTask.terminationHandler = ^(NSTask* task)
// termination handler

self.ffMPEGTask = theTask;

[theTask release];

if( self.ffMPEGTask )
[self.ffMPEGTask launch]; // GO!!!
self.status = XVMediaDownloaderRunning;
self.filesize = 0;


On 9 Jul 2019, at 4:01 pm, Chris Hanson <cmhanson@...> wrote:

Sure, just use NSTask’s own standardInput, standardOutput, and standardError support with NSPipe. No need to tell the task to send its stdout to some intermediate file that your app then opens and reads from. (Whether it’s in /dev or anywhere else.)

 -- Chris

Join { to automatically receive all group messages.