objective c - Unable to get intermediate output from NSTask's stdout? -


i have written nstask async exec method simple python script.

when python script prints stdout, fine. when there raw_input in there (expecting input user), sure gets input fine, not print data before raw_input.

what's going on?

- (nsstring*)exec:(nsarray *)args environment:(nsdictionary*)env action:(void (^)(nsstring*))action completed:(void (^)(nsstring*))completed {     _task                           = [nstask new];     _output                         = [nspipe new];     _error                          = [nspipe new];     _input                          = [nspipe new];     nsfilehandle* outputf           = [_output filehandleforreading];     nsfilehandle* errorf            = [_error filehandleforreading];     nsfilehandle* inputf            = [_input filehandleforwriting];      __block nsstring* fulloutput    = @"";      nsmutabledictionary* envs = [nsmutabledictionary dictionary];      nsarray* newargs = @[@"bash",@"-c"];      [_task setlaunchpath:@"/usr/bin/env"];     if (env)         (nsstring* key in env)             envs[key] = env[key];      if ([envs count]) [_task setenvironment:envs];      nsstring* cmd = @"";      cmd = [cmd stringbyappendingstring:[[[self sanitizedargs:args] componentsjoinedbystring:@" "] stringbyappendingstring:@" && echo \":::::$pwd:::::\""]];      [_task setarguments:[newargs arraybyaddingobject:cmd]];     [_task setstandardoutput:_output];     [_task setstandarderror:_error];     [_task setstandardinput:_input];      void (^outputter)(nsfilehandle*) = ^(nsfilehandle *file){         nsdata *data = [file availabledata];         nsstring* str = [[nsstring alloc] initwithdata:data encoding:nsutf8stringencoding];          nslog(@"output: %@",str);          action(str);         fulloutput = [fulloutput stringbyappendingstring:str];     };      void (^inputter)(nsfilehandle*) = ^(nsfilehandle *file) {         nslog(@"in inputter");         nsdata *data = [[_task.standardoutput filehandleforreading] availabledata];         nsstring* str = [[nsstring alloc] initwithdata:data encoding:nsutf8stringencoding];          nslog(@"output: %@",str);     };      [outputf setreadabilityhandler:outputter];     [errorf setreadabilityhandler:outputter];     //[inputf setwriteabilityhandler:inputter];      [_task setterminationhandler:^(nstask* task){         nslog(@"terminated: %@",fulloutput);         completed(fulloutput);          //[task.standardoutput filehandleforreading].readabilityhandler = nil;         //[task.standarderror filehandleforreading].readabilityhandler = nil;         //[task.standardinput filehandleforwriting].writeabilityhandler = nil;         //[task terminate];         //task = nil;     }];      [_task launch];      //[[_input filehandleforwriting] waitfordatainbackgroundandnotify];      return @""; } 

p.s. i've searched everywhere solution, didn't seem spot anything. looks there tons of nstask walkthroughs , tutorials, - funny coincidence - avoid dealing of stdin implications

this doesn't have parent process (the 1 nstask object). it's behavior of child process. child process literally not writing bytes pipe (yet).

from stdio man page:

initially, standard error stream unbuffered; standard input , output streams buffered if , if streams not refer interactive or “terminal” device, determined isatty(3) function. in fact, all freshly-opened streams refer terminal devices default line buffering, , pending output such streams written automatically whenever such input stream read. note applies ``true reads''; if read request can satisfied existing buffered data, no automatic flush occur. in these cases, or when large amount of computation done after printing part of line on output terminal, necessary fflush(3) standard output before going off , computing output appear. alternatively, these defaults may modified via setvbuf(3) function.

in case, standard input , output not, in fact, refer interactive/terminal device. so, standard output buffered (a.k.a. block buffered, opposed line buffered or unbuffered). flushed when buffer internal stdio library full, when stream closed, or when fflush() called on stream.

the behavior you're expecting, standard output flushed automatically when input read, happens in case streams connected interactive/terminal device.

there no way parent process influence buffering behavior of child process except using pseudo-terminal device rather pipe input , output. however, that's complex , error-prone undertaking. other that, child process has coded set buffering mode of standard output or flush regularly.


Comments

Popular posts from this blog

ruby on rails - RuntimeError: Circular dependency detected while autoloading constant - ActiveAdmin.register Role -

c++ - OpenMP unpredictable overhead -

javascript - Wordpress slider, not displayed 100% width -