1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <lib/async/cpp/exception.h>
6
7 #include <utility>
8
9 namespace async {
10
ExceptionBase(zx_handle_t task,uint32_t options,async_exception_handler_t * handler)11 ExceptionBase::ExceptionBase(zx_handle_t task, uint32_t options,
12 async_exception_handler_t* handler)
13 : exception_{{ASYNC_STATE_INIT}, handler, task, options} {
14 ZX_DEBUG_ASSERT(handler);
15 }
16
~ExceptionBase()17 ExceptionBase::~ExceptionBase() {
18 if (dispatcher_) {
19 // Failure to unbind here may result in a dangling pointer...
20 zx_status_t status = async_unbind_exception_port(dispatcher_, &exception_);
21 ZX_ASSERT_MSG(status == ZX_OK, "status=%d", status);
22 }
23 }
24
Bind(async_dispatcher_t * dispatcher)25 zx_status_t ExceptionBase::Bind(async_dispatcher_t* dispatcher) {
26 if (dispatcher_)
27 return ZX_ERR_ALREADY_EXISTS;
28
29 dispatcher_ = dispatcher;
30 zx_status_t status = async_bind_exception_port(dispatcher, &exception_);
31 if (status != ZX_OK) {
32 dispatcher_ = nullptr;
33 }
34 return status;
35 }
36
Unbind()37 zx_status_t ExceptionBase::Unbind() {
38 if (!dispatcher_)
39 return ZX_ERR_NOT_FOUND;
40
41 async_dispatcher_t* dispatcher = dispatcher_;
42 dispatcher_ = nullptr;
43
44 zx_status_t status = async_unbind_exception_port(dispatcher, &exception_);
45 // |dispatcher| is required to be single-threaded, Unbind() is
46 // only supposed to be called on |dispatcher|'s thread, and
47 // we verified that the port was bound before calling
48 // async_unbind_exception_port().
49 ZX_DEBUG_ASSERT(status != ZX_ERR_NOT_FOUND);
50 return status;
51 }
52
Resume(zx_handle_t task,uint32_t options)53 zx_status_t ExceptionBase::Resume(zx_handle_t task, uint32_t options) {
54 if (!dispatcher_)
55 return ZX_ERR_NOT_FOUND;
56
57 return async_resume_from_exception(dispatcher_, &exception_, task, options);
58 }
59
Exception(zx_handle_t task,uint32_t options,Handler handler)60 Exception::Exception(zx_handle_t task, uint32_t options,
61 Handler handler)
62 : ExceptionBase(task, options, &Exception::CallHandler),
63 handler_(std::move(handler)) {}
64
65 Exception::~Exception() = default;
66
CallHandler(async_dispatcher_t * dispatcher,async_exception_t * exception,zx_status_t status,const zx_port_packet_t * report)67 void Exception::CallHandler(async_dispatcher_t* dispatcher,
68 async_exception_t* exception,
69 zx_status_t status,
70 const zx_port_packet_t* report) {
71 auto self = Dispatch<Exception>(exception);
72 self->handler_(dispatcher, self, status, report);
73 }
74
75 } // namespace async
76