libutil: fix segfault in makeInterruptible callback
cancelling the promise returned by makeInterruptible could free the fulfiller before the interrupt callback handle, and no order of the attachments made a difference. we must resort to putting fulfillers into shared_ptrs so we can capture them in interrupt callbacks now. (alternatively we could add another kind of interrupt callback, but the complexity of doing that outweighs the cost of one shared_ptr.) fixes #895 Change-Id: I008b160482fd4d81a29d7e9e452dcda858b090b9
This commit is contained in:
@@ -124,11 +124,14 @@ template<typename T>
|
||||
kj::Promise<Result<T>> makeInterruptible(kj::Promise<Result<T>> p)
|
||||
{
|
||||
auto onInterrupt = kj::newPromiseAndCrossThreadFulfiller<Result<T>>();
|
||||
auto interruptCallback = createInterruptCallback([fulfiller{onInterrupt.fulfiller.get()}] {
|
||||
fulfiller->fulfill(result::failure(std::make_exception_ptr(makeInterrupted())));
|
||||
// the fulfiller must be a shared_ptr<Own<...>> since functions must
|
||||
// be copyable, and we don't have move_only_function on all stdlibs.
|
||||
auto fulfiller =
|
||||
std::make_shared<decltype(onInterrupt.fulfiller)>(std::move(onInterrupt.fulfiller));
|
||||
auto interruptCallback = createInterruptCallback([fulfiller] {
|
||||
(*fulfiller)->fulfill(result::failure(std::make_exception_ptr(makeInterrupted())));
|
||||
});
|
||||
return p.attach(std::move(onInterrupt.fulfiller), std::move(interruptCallback))
|
||||
.exclusiveJoin(std::move(onInterrupt.promise));
|
||||
return p.attach(std::move(interruptCallback)).exclusiveJoin(std::move(onInterrupt.promise));
|
||||
}
|
||||
|
||||
void triggerInterrupt();
|
||||
|
||||
Reference in New Issue
Block a user