aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-10-10 21:00:39 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-10-10 21:00:39 -0700
commit2292ef8d0e2c0f5ac5523dfb919c4156ad4ea4fb (patch)
tree769fdf7fa0f5fa78776277ba095495d6c39e9fe4 /src
parenta114af4eea794e8b6a76b7cadc8f18730a52e8ad (diff)
downloadbun-2292ef8d0e2c0f5ac5523dfb919c4156ad4ea4fb.tar.gz
bun-2292ef8d0e2c0f5ac5523dfb919c4156ad4ea4fb.tar.zst
bun-2292ef8d0e2c0f5ac5523dfb919c4156ad4ea4fb.zip
Keep the process alive
Diffstat (limited to 'src')
-rw-r--r--src/bun.js/api/bun.classes.ts5
-rw-r--r--src/bun.js/api/bun.zig2
-rw-r--r--src/bun.js/api/bun/subprocess.zig35
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.cpp43
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.h5
-rw-r--r--src/bun.js/event_loop.zig57
-rw-r--r--src/bun.js/javascript.zig1
7 files changed, 62 insertions, 86 deletions
diff --git a/src/bun.js/api/bun.classes.ts b/src/bun.js/api/bun.classes.ts
index bbb1df944..2f688bb9c 100644
--- a/src/bun.js/api/bun.classes.ts
+++ b/src/bun.js/api/bun.classes.ts
@@ -21,11 +21,11 @@ export default [
},
writable: {
getter: "getStdin",
- cache: true,
+ cache: "stdin",
},
readable: {
getter: "getStdout",
- cache: true,
+ cache: "stdout",
},
stderr: {
getter: "getStderr",
@@ -56,7 +56,6 @@ export default [
exited: {
getter: "getExited",
- cache: true,
},
},
}),
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig
index 9b50746c5..007538a6a 100644
--- a/src/bun.js/api/bun.zig
+++ b/src/bun.js/api/bun.zig
@@ -1522,7 +1522,7 @@ pub fn serve(
exception: js.ExceptionRef,
) js.JSValueRef {
var args = JSC.Node.ArgumentsSlice.from(ctx.bunVM(), arguments);
- var config = JSC.API.ServerConfig.fromJS(ctx.ptr(), &args, exception);
+ const config = JSC.API.ServerConfig.fromJS(ctx.ptr(), &args, exception);
if (exception.* != null) {
return null;
}
diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig
index 0c5d0ce2b..9fac2ee37 100644
--- a/src/bun.js/api/bun/subprocess.zig
+++ b/src/bun.js/api/bun/subprocess.zig
@@ -33,8 +33,13 @@ pub const Subprocess = struct {
reffer: JSC.Ref = JSC.Ref.init(),
poll_ref: JSC.PollRef = JSC.PollRef.init(),
- exit_promise: JSValue = JSValue.zero,
- this_jsvalue: JSValue = JSValue.zero,
+ exit_promise: JSC.Strong = .{},
+
+ /// Keep the JSValue alive until the process is done by default
+ /// Unless you call unref()
+ this_jsvalue: JSC.Strong = .{},
+
+ on_exit_callback: JSC.Strong = .{},
exit_code: ?u8 = null,
waitpid_err: ?JSC.Node.Syscall.Error = null,
@@ -49,14 +54,13 @@ pub const Subprocess = struct {
globalThis: *JSC.JSGlobalObject,
- on_exit_callback: JSC.Strong = .{},
-
pub fn ref(this: *Subprocess) void {
this.reffer.ref(this.globalThis.bunVM());
this.poll_ref.ref(this.globalThis.bunVM());
}
pub fn unref(this: *Subprocess) void {
+ this.this_jsvalue.clear();
this.reffer.unref(this.globalThis.bunVM());
this.poll_ref.unref(this.globalThis.bunVM());
}
@@ -279,7 +283,8 @@ pub const Subprocess = struct {
this.stdin.close();
}
- pub fn doRef(this: *Subprocess, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue {
+ pub fn doRef(this: *Subprocess, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue {
+ this.this_jsvalue.set(globalThis, callframe.this());
this.ref();
return JSC.JSValue.jsUndefined();
}
@@ -349,6 +354,10 @@ pub const Subprocess = struct {
return;
}
+ if (comptime bun.Environment.allow_assert) {
+ // bun.assertNonBlocking(this.fd);
+ }
+
while (to_write.len > 0) {
switch (JSC.Node.Syscall.write(this.fd, to_write)) {
.err => |e| {
@@ -700,11 +709,11 @@ pub const Subprocess = struct {
return JSC.JSPromise.resolvedPromiseValue(globalThis, JSC.JSValue.jsNumber(code));
}
- if (this.exit_promise == .zero) {
- this.exit_promise = JSC.JSPromise.create(globalThis).asValue(globalThis);
+ if (!this.exit_promise.has()) {
+ this.exit_promise.set(globalThis, JSC.JSPromise.create(globalThis).asValue(globalThis));
}
- return this.exit_promise;
+ return this.exit_promise.get().?;
}
pub fn getExitCode(
@@ -1025,8 +1034,8 @@ pub const Subprocess = struct {
subprocess.stdin.pipe.signal = JSC.WebCore.Signal.init(&subprocess.stdin);
}
- subprocess.this_jsvalue = subprocess.toJS(globalThis);
- subprocess.this_jsvalue.ensureStillAlive();
+ const out = subprocess.toJS(globalThis);
+ subprocess.this_jsvalue.set(globalThis, out);
switch (globalThis.bunVM().poller.watch(
@intCast(JSC.Node.FileDescriptor, pidfd),
@@ -1064,7 +1073,7 @@ pub const Subprocess = struct {
subprocess.stderr.pipe.buffer.readIfPossible();
}
- return subprocess.this_jsvalue;
+ return out;
}
pub fn onExitNotification(
@@ -1114,9 +1123,7 @@ pub const Subprocess = struct {
}
}
- if (this.exit_promise != .zero) {
- var promise = this.exit_promise;
- this.exit_promise = .zero;
+ if (this.exit_promise.trySwap()) |promise| {
if (this.exit_code) |code| {
promise.asPromise().?.resolve(this.globalThis, JSValue.jsNumber(code));
} else if (this.waitpid_err) |err| {
diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp
index ec53d56ba..c737103fc 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses.cpp
+++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp
@@ -131,19 +131,12 @@ JSC_DEFINE_CUSTOM_GETTER(SubprocessPrototype__exitedGetterWrap, (JSGlobalObject
Zig::GlobalObject *globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
auto throwScope = DECLARE_THROW_SCOPE(vm);
JSSubprocess* thisObject = jsCast<JSSubprocess*>(JSValue::decode(thisValue));
- JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
-
- if (JSValue cachedValue = thisObject->m_exited.get())
- return JSValue::encode(cachedValue);
-
- JSC::JSValue result = JSC::JSValue::decode(
- SubprocessPrototype__getExited(thisObject->wrapped(), globalObject)
- );
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ JSC::EncodedJSValue result = SubprocessPrototype__getExited(thisObject->wrapped(), globalObject);
RETURN_IF_EXCEPTION(throwScope, {});
- thisObject->m_exited.set(vm, thisObject, result);
- RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
+ RELEASE_AND_RETURN(throwScope, result);
}
-
+
JSC_DEFINE_HOST_FUNCTION(SubprocessPrototype__killCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
{
@@ -196,14 +189,14 @@ JSC_DEFINE_CUSTOM_GETTER(SubprocessPrototype__readableGetterWrap, (JSGlobalObjec
JSSubprocess* thisObject = jsCast<JSSubprocess*>(JSValue::decode(thisValue));
JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
- if (JSValue cachedValue = thisObject->m_readable.get())
+ if (JSValue cachedValue = thisObject->m_stdout.get())
return JSValue::encode(cachedValue);
JSC::JSValue result = JSC::JSValue::decode(
SubprocessPrototype__getStdout(thisObject->wrapped(), globalObject)
);
RETURN_IF_EXCEPTION(throwScope, {});
- thisObject->m_readable.set(vm, thisObject, result);
+ thisObject->m_stdout.set(vm, thisObject, result);
RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
}
@@ -310,14 +303,14 @@ JSC_DEFINE_CUSTOM_GETTER(SubprocessPrototype__writableGetterWrap, (JSGlobalObjec
JSSubprocess* thisObject = jsCast<JSSubprocess*>(JSValue::decode(thisValue));
JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
- if (JSValue cachedValue = thisObject->m_writable.get())
+ if (JSValue cachedValue = thisObject->m_stdin.get())
return JSValue::encode(cachedValue);
JSC::JSValue result = JSC::JSValue::decode(
SubprocessPrototype__getStdin(thisObject->wrapped(), globalObject)
);
RETURN_IF_EXCEPTION(throwScope, {});
- thisObject->m_writable.set(vm, thisObject, result);
+ thisObject->m_stdin.set(vm, thisObject, result);
RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
}
@@ -422,7 +415,6 @@ JSSubprocess* JSSubprocess::create(JSC::VM& vm, JSC::JSGlobalObject* globalObjec
return ptr;
}
-
extern "C" void* Subprocess__fromJS(JSC::EncodedJSValue value) {
JSSubprocess* object = JSC::jsDynamicCast<JSSubprocess*>(JSValue::decode(value));
if (!object)
@@ -465,12 +457,10 @@ void JSSubprocess::visitChildrenImpl(JSCell* cell, Visitor& visitor)
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
- visitor.append(thisObject->m_exited);
- visitor.append(thisObject->m_readable);
+
visitor.append(thisObject->m_stderr);
visitor.append(thisObject->m_stdin);
visitor.append(thisObject->m_stdout);
- visitor.append(thisObject->m_writable);
}
DEFINE_VISIT_CHILDREN(JSSubprocess);extern "C" void* SHA1Class__construct(JSC::JSGlobalObject*, JSC::CallFrame*);
@@ -673,7 +663,6 @@ JSSHA1* JSSHA1::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Stru
return ptr;
}
-
extern "C" void* SHA1__fromJS(JSC::EncodedJSValue value) {
JSSHA1* object = JSC::jsDynamicCast<JSSHA1*>(JSValue::decode(value));
if (!object)
@@ -907,7 +896,6 @@ JSMD5* JSMD5::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Struct
return ptr;
}
-
extern "C" void* MD5__fromJS(JSC::EncodedJSValue value) {
JSMD5* object = JSC::jsDynamicCast<JSMD5*>(JSValue::decode(value));
if (!object)
@@ -1141,7 +1129,6 @@ JSMD4* JSMD4::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Struct
return ptr;
}
-
extern "C" void* MD4__fromJS(JSC::EncodedJSValue value) {
JSMD4* object = JSC::jsDynamicCast<JSMD4*>(JSValue::decode(value));
if (!object)
@@ -1375,7 +1362,6 @@ JSSHA224* JSSHA224::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::
return ptr;
}
-
extern "C" void* SHA224__fromJS(JSC::EncodedJSValue value) {
JSSHA224* object = JSC::jsDynamicCast<JSSHA224*>(JSValue::decode(value));
if (!object)
@@ -1609,7 +1595,6 @@ JSSHA512* JSSHA512::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::
return ptr;
}
-
extern "C" void* SHA512__fromJS(JSC::EncodedJSValue value) {
JSSHA512* object = JSC::jsDynamicCast<JSSHA512*>(JSValue::decode(value));
if (!object)
@@ -1843,7 +1828,6 @@ JSSHA384* JSSHA384::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::
return ptr;
}
-
extern "C" void* SHA384__fromJS(JSC::EncodedJSValue value) {
JSSHA384* object = JSC::jsDynamicCast<JSSHA384*>(JSValue::decode(value));
if (!object)
@@ -2077,7 +2061,6 @@ JSSHA256* JSSHA256::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::
return ptr;
}
-
extern "C" void* SHA256__fromJS(JSC::EncodedJSValue value) {
JSSHA256* object = JSC::jsDynamicCast<JSSHA256*>(JSValue::decode(value));
if (!object)
@@ -2311,7 +2294,6 @@ JSSHA512_256* JSSHA512_256::create(JSC::VM& vm, JSC::JSGlobalObject* globalObjec
return ptr;
}
-
extern "C" void* SHA512_256__fromJS(JSC::EncodedJSValue value) {
JSSHA512_256* object = JSC::jsDynamicCast<JSSHA512_256*>(JSValue::decode(value));
if (!object)
@@ -2539,7 +2521,6 @@ JSTextDecoder* JSTextDecoder::create(JSC::VM& vm, JSC::JSGlobalObject* globalObj
return ptr;
}
-
extern "C" void* TextDecoder__fromJS(JSC::EncodedJSValue value) {
JSTextDecoder* object = JSC::jsDynamicCast<JSTextDecoder*>(JSValue::decode(value));
if (!object)
@@ -2582,6 +2563,7 @@ void JSTextDecoder::visitChildrenImpl(JSCell* cell, Visitor& visitor)
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
+
visitor.append(thisObject->m_encoding);
}
@@ -3083,7 +3065,6 @@ JSRequest* JSRequest::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC
return ptr;
}
-
extern "C" void* Request__fromJS(JSC::EncodedJSValue value) {
JSRequest* object = JSC::jsDynamicCast<JSRequest*>(JSValue::decode(value));
if (!object)
@@ -3125,6 +3106,7 @@ void JSRequest::visitChildrenImpl(JSCell* cell, Visitor& visitor)
JSRequest* thisObject = jsCast<JSRequest*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
+
if (auto* ptr = thisObject->wrapped()) {
visitor.reportExtraMemoryVisited(Request__estimatedSize(ptr));
}
@@ -3574,7 +3556,6 @@ JSResponse* JSResponse::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, J
return ptr;
}
-
extern "C" void* Response__fromJS(JSC::EncodedJSValue value) {
JSResponse* object = JSC::jsDynamicCast<JSResponse*>(JSValue::decode(value));
if (!object)
@@ -3616,6 +3597,7 @@ void JSResponse::visitChildrenImpl(JSCell* cell, Visitor& visitor)
JSResponse* thisObject = jsCast<JSResponse*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
+
if (auto* ptr = thisObject->wrapped()) {
visitor.reportExtraMemoryVisited(Response__estimatedSize(ptr));
}
@@ -3938,7 +3920,6 @@ JSBlob* JSBlob::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Stru
return ptr;
}
-
extern "C" void* Blob__fromJS(JSC::EncodedJSValue value) {
JSBlob* object = JSC::jsDynamicCast<JSBlob*>(JSValue::decode(value));
if (!object)
diff --git a/src/bun.js/bindings/ZigGeneratedClasses.h b/src/bun.js/bindings/ZigGeneratedClasses.h
index 7b2afdf2d..b51637efa 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses.h
@@ -66,12 +66,9 @@ class JSSubprocess final : public JSC::JSDestructibleObject {
DECLARE_VISIT_CHILDREN;
- mutable JSC::WriteBarrier<JSC::Unknown> m_exited;
-mutable JSC::WriteBarrier<JSC::Unknown> m_readable;
-mutable JSC::WriteBarrier<JSC::Unknown> m_stderr;
+ mutable JSC::WriteBarrier<JSC::Unknown> m_stderr;
mutable JSC::WriteBarrier<JSC::Unknown> m_stdin;
mutable JSC::WriteBarrier<JSC::Unknown> m_stdout;
-mutable JSC::WriteBarrier<JSC::Unknown> m_writable;
};
class JSSubprocessPrototype final : public JSC::JSNonFinalObject {
public:
diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig
index 331d939e2..b395e8377 100644
--- a/src/bun.js/event_loop.zig
+++ b/src/bun.js/event_loop.zig
@@ -226,7 +226,6 @@ pub const EventLoop = struct {
waker: ?AsyncIO.Waker = null,
start_server_on_next_tick: bool = false,
defer_count: std.atomic.Atomic(usize) = std.atomic.Atomic(usize).init(0),
- pending_processes_to_exit: std.AutoArrayHashMap(*JSC.Subprocess, void) = undefined,
pub const Queue = std.fifo.LinearFifo(Task, .Dynamic);
@@ -336,7 +335,7 @@ pub const EventLoop = struct {
pub fn autoTick(this: *EventLoop) void {
if (this.virtual_machine.uws_event_loop.?.num_polls > 0 or this.virtual_machine.uws_event_loop.?.active > 0) {
this.virtual_machine.uws_event_loop.?.tick();
- this.afterUSocketsTick();
+ // this.afterUSocketsTick();
}
}
@@ -433,16 +432,6 @@ pub const EventLoop = struct {
}
}
- pub fn afterUSocketsTick(this: *EventLoop) void {
- const processes = this.pending_processes_to_exit.keys();
- if (processes.len > 0) {
- for (processes) |process| {
- process.onExitNotification();
- }
- this.pending_processes_to_exit.clearRetainingCapacity();
- }
- }
-
pub fn enqueueTaskConcurrent(this: *EventLoop, task: *ConcurrentTask) void {
JSC.markBinding();
@@ -476,10 +465,7 @@ pub const Poller = struct {
var loader = ptr.as(JSC.Subprocess);
loader.poll_ref.deactivate(loop);
-
- // kqueue sends the same notification multiple times in the same tick potentially
- // so we have to dedupe it
- _ = loader.globalThis.bunVM().eventLoop().pending_processes_to_exit.getOrPut(loader) catch unreachable;
+ loader.onExitNotification();
},
@field(Pollable.Tag, "BufferedInput") => {
var loader = ptr.as(JSC.Subprocess.BufferedInput);
@@ -523,9 +509,7 @@ pub const Poller = struct {
var loader = ptr.as(JSC.Subprocess);
loader.poll_ref.deactivate(loop);
- // kqueue sends the same notification multiple times in the same tick potentially
- // so we have to dedupe it
- _ = loader.globalThis.bunVM().eventLoop().pending_processes_to_exit.getOrPut(loader) catch unreachable;
+ loader.onExitNotification();
},
@field(Pollable.Tag, "FileSink") => {
var loader = ptr.as(JSC.WebCore.FileSink);
@@ -611,7 +595,7 @@ pub const Poller = struct {
.data = 0,
.fflags = 0,
.udata = @ptrToInt(Pollable.init(ctx).ptr()),
- .flags = std.c.EV_ADD | std.c.EV_ENABLE | std.c.EV_ONESHOT,
+ .flags = std.c.EV_ADD | std.c.EV_ONESHOT,
.ext = .{ 0, 0 },
},
.write => .{
@@ -620,7 +604,7 @@ pub const Poller = struct {
.data = 0,
.fflags = 0,
.udata = @ptrToInt(Pollable.init(ctx).ptr()),
- .flags = std.c.EV_ADD | std.c.EV_ENABLE | std.c.EV_ONESHOT,
+ .flags = std.c.EV_ADD | std.c.EV_ONESHOT,
.ext = .{ 0, 0 },
},
.process => .{
@@ -629,7 +613,7 @@ pub const Poller = struct {
.data = 0,
.fflags = std.c.NOTE_EXIT,
.udata = @ptrToInt(Pollable.init(ctx).ptr()),
- .flags = std.c.EV_ADD | std.c.EV_ENABLE | std.c.EV_ONESHOT,
+ .flags = std.c.EV_ADD,
.ext = .{ 0, 0 },
},
};
@@ -640,16 +624,24 @@ pub const Poller = struct {
// The kevent() system call returns the number of events placed in
// the eventlist, up to the value given by nevents. If the time
// limit expires, then kevent() returns 0.
- const rc = std.os.system.kevent64(
- watcher_fd,
- &changelist,
- 1,
- // The same array may be used for the changelist and eventlist.
- &changelist,
- 1,
- KEVENT_FLAG_ERROR_EVENTS,
- &timeout,
- );
+ const rc = rc: {
+ while (true) {
+ const rc = std.os.system.kevent64(
+ watcher_fd,
+ &changelist,
+ 1,
+ // The same array may be used for the changelist and eventlist.
+ &changelist,
+ 1,
+ KEVENT_FLAG_ERROR_EVENTS,
+ &timeout,
+ );
+
+ if (std.c.getErrno(rc) == .INTR) continue;
+ break :rc rc;
+ }
+ };
+
// If an error occurs while
// processing an element of the changelist and there is enough room
// in the eventlist, then the event will be placed in the eventlist
@@ -664,6 +656,7 @@ pub const Poller = struct {
if (errno == .SUCCESS) {
ctx.poll_ref.activate(this.loop.?);
+
return JSC.Maybe(void).success;
}
diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig
index 8fccee097..6fc8984f8 100644
--- a/src/bun.js/javascript.zig
+++ b/src/bun.js/javascript.zig
@@ -577,7 +577,6 @@ pub const VirtualMachine = struct {
VirtualMachine.vm.regular_event_loop.tasks = EventLoop.Queue.init(
default_allocator,
);
- VirtualMachine.vm.regular_event_loop.pending_processes_to_exit = std.AutoArrayHashMap(*JSC.Subprocess, void).init(allocator);
VirtualMachine.vm.regular_event_loop.tasks.ensureUnusedCapacity(64) catch unreachable;
VirtualMachine.vm.regular_event_loop.concurrent_tasks = .{};
VirtualMachine.vm.event_loop = &VirtualMachine.vm.regular_event_loop;