mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2025-01-05 22:04:34 +03:00
ChildProcess can handle commands that return large amounts of data.
When a command returned a large amount of data, it was blocking on the stderr callback when `[fileHandle availableData]` was called. From what I can tell, this is because stderr was being called with a zero-length string. This was fixed when `[fileHandle availableData]` was moved to run inside the NSTask thread (instead of on the main thread). It now returns a zero-length string rather than blocking forever. An unresolved question is why stderr is being called with zero-length strings.
This commit is contained in:
parent
ea088db19d
commit
1bd0cc4152
@ -406,15 +406,12 @@ bool Native::Execute(const CefString& name,
|
||||
[task setStandardError:stderr];
|
||||
|
||||
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
|
||||
void (^outputHandle)(NSFileHandle *fileHandle, CefRefPtr<CefV8Value> function) = nil;
|
||||
void (^outputHandle)(NSString *contents, CefRefPtr<CefV8Value> function) = nil;
|
||||
void (^taskTerminatedHandle)() = nil;
|
||||
|
||||
outputHandle = ^(NSFileHandle *fileHandle, CefRefPtr<CefV8Value> function) {
|
||||
outputHandle = ^(NSString *contents, CefRefPtr<CefV8Value> function) {
|
||||
context->Enter();
|
||||
|
||||
NSData *data = [fileHandle availableData];
|
||||
NSString *contents = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
|
||||
CefV8ValueList args;
|
||||
args.push_back(CefV8Value::CreateString(std::string([contents UTF8String], [contents lengthOfBytesUsingEncoding:NSUTF8StringEncoding])));
|
||||
CefRefPtr<CefV8Value> retval = function->ExecuteFunction(function, args);
|
||||
@ -423,7 +420,6 @@ bool Native::Execute(const CefString& name,
|
||||
throwException(context->GetGlobal(), function->GetException(), @"Error thrown in OutputHandle");
|
||||
}
|
||||
|
||||
[contents release];
|
||||
context->Exit();
|
||||
};
|
||||
|
||||
@ -457,18 +453,24 @@ bool Native::Execute(const CefString& name,
|
||||
CefRefPtr<CefV8Value> stdoutFunction = options->GetValue("stdout");
|
||||
if (stdoutFunction->IsFunction()) {
|
||||
stdout.fileHandleForReading.writeabilityHandler = ^(NSFileHandle *fileHandle) {
|
||||
NSData *data = [fileHandle availableData];
|
||||
NSString *contents = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
dispatch_sync(dispatch_get_main_queue(), ^() {
|
||||
outputHandle(fileHandle, stdoutFunction);
|
||||
outputHandle(contents, stdoutFunction);
|
||||
});
|
||||
[contents release];
|
||||
};
|
||||
}
|
||||
|
||||
CefRefPtr<CefV8Value> stderrFunction = options->GetValue("stderr");
|
||||
if (stderrFunction->IsFunction()) {
|
||||
stderr.fileHandleForReading.writeabilityHandler = ^(NSFileHandle *fileHandle) {
|
||||
NSData *data = [fileHandle availableData];
|
||||
NSString *contents = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
dispatch_sync(dispatch_get_main_queue(), ^() {
|
||||
outputHandle(fileHandle, stderrFunction);
|
||||
outputHandle(contents, stderrFunction);
|
||||
});
|
||||
[contents release];
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -104,3 +104,26 @@ describe 'Child Processes', ->
|
||||
ChildProcess.exec(cmd, options).fail (error) ->
|
||||
expect(error.exitStatus).toBe 2
|
||||
expect(errorOutput).toBe "bad\n"
|
||||
|
||||
describe "when a command returns a large amount of data (over 10k)", ->
|
||||
originalTimeout = null
|
||||
beforeEach ->
|
||||
originalTimeout = jasmine.getEnv().defaultTimeoutInterval
|
||||
jasmine.getEnv().defaultTimeoutInterval = 1000
|
||||
|
||||
afterEach ->
|
||||
jasmine.getEnv().defaultTimeoutInterval = originalTimeout
|
||||
|
||||
it "does not block indefinitally on stdout or stderr callbacks (regression)", ->
|
||||
output = []
|
||||
|
||||
waitsForPromise ->
|
||||
cmd = "for i in {1..20000}; do echo $RANDOM; done"
|
||||
options =
|
||||
stdout: (data) -> output.push(data)
|
||||
stderr: (data) -> console.log data.length
|
||||
|
||||
ChildProcess.exec(cmd, options)
|
||||
|
||||
runs ->
|
||||
expect(output.length).toBeGreaterThan 1
|
Loading…
Reference in New Issue
Block a user