fix: improve CallContext robustness
This commit is contained in:
parent
d7dd271163
commit
2b380bbef4
1 changed files with 19 additions and 21 deletions
|
@ -109,7 +109,7 @@ fn Pid(comptime own: Ownership) type {
|
||||||
return c.thespian_handle_is_expired(self.h);
|
return c.thespian_handle_is_expired(self.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_expired(self: Self, timeout_ns: isize) !void {
|
pub fn wait_expired(self: Self, timeout_ns: isize) error{Timeout}!void {
|
||||||
var max_sleep: isize = timeout_ns;
|
var max_sleep: isize = timeout_ns;
|
||||||
while (!self.expired()) {
|
while (!self.expired()) {
|
||||||
if (max_sleep <= 0) return error.Timeout;
|
if (max_sleep <= 0) return error.Timeout;
|
||||||
|
@ -798,9 +798,10 @@ pub const file_stream = struct {
|
||||||
|
|
||||||
const CallContext = struct {
|
const CallContext = struct {
|
||||||
receiver: ReceiverT,
|
receiver: ReceiverT,
|
||||||
|
from: pid,
|
||||||
to: pid_ref,
|
to: pid_ref,
|
||||||
request: message,
|
request: message,
|
||||||
response: *?message,
|
response: ?message,
|
||||||
a: std.mem.Allocator,
|
a: std.mem.Allocator,
|
||||||
done: std.Thread.ResetEvent = .{},
|
done: std.Thread.ResetEvent = .{},
|
||||||
|
|
||||||
|
@ -808,29 +809,21 @@ const CallContext = struct {
|
||||||
const ReceiverT = Receiver(*Self);
|
const ReceiverT = Receiver(*Self);
|
||||||
|
|
||||||
pub fn call(a: std.mem.Allocator, to: pid_ref, timeout_ns: u64, request: message) CallError!message {
|
pub fn call(a: std.mem.Allocator, to: pid_ref, timeout_ns: u64, request: message) CallError!message {
|
||||||
var response: ?message = null;
|
const self = try a.create(Self);
|
||||||
var self: Self = .{
|
self.* = .{
|
||||||
.receiver = undefined,
|
.receiver = undefined,
|
||||||
|
.from = self_pid().clone(),
|
||||||
.to = to,
|
.to = to,
|
||||||
.request = request,
|
.request = request,
|
||||||
.response = &response,
|
.response = null,
|
||||||
.a = a,
|
.a = a,
|
||||||
};
|
};
|
||||||
self.receiver = ReceiverT.init(receive_, &self);
|
self.receiver = ReceiverT.init(receive_, self);
|
||||||
const proc = try spawn_link(a, &self, start, @typeName(Self));
|
const proc = try spawn_link(a, self, start, @typeName(Self));
|
||||||
defer proc.deinit();
|
defer proc.deinit();
|
||||||
errdefer {
|
try self.done.timedWait(timeout_ns);
|
||||||
proc.send(.{"timeout"}) catch @panic("CallContext.send.timeout");
|
defer self.deinit(); // only deinit on success. if we timed out proc will have to deinit
|
||||||
self.done.wait();
|
return self.response orelse .{};
|
||||||
if (response) |resp| a.free(resp.buf);
|
|
||||||
}
|
|
||||||
self.done.timedWait(timeout_ns) catch |e| switch (e) {
|
|
||||||
error.Timeout => {
|
|
||||||
return e;
|
|
||||||
},
|
|
||||||
else => return e,
|
|
||||||
};
|
|
||||||
return response orelse .{};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: *Self) void {
|
fn deinit(self: *Self) void {
|
||||||
|
@ -846,8 +839,13 @@ const CallContext = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive_(self: *Self, _: pid_ref, m: message) result {
|
fn receive_(self: *Self, _: pid_ref, m: message) result {
|
||||||
defer self.done.set();
|
defer {
|
||||||
self.response.* = m.clone(self.a) catch |e| return exit_error(e, @errorReturnTrace());
|
const expired = self.from.expired();
|
||||||
|
self.from.deinit();
|
||||||
|
self.done.set();
|
||||||
|
if (expired) self.deinit();
|
||||||
|
}
|
||||||
|
self.response = m.clone(self.a) catch |e| return exit_error(e, @errorReturnTrace());
|
||||||
return exit_normal();
|
return exit_normal();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue