1 | /* |
2 | * Copyright (c) Facebook, Inc. and its affiliates. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #include <folly/ExceptionWrapper.h> |
18 | |
19 | #include <iostream> |
20 | |
21 | #include <folly/GLog.h> |
22 | |
23 | namespace folly { |
24 | |
25 | exception_wrapper::VTable const exception_wrapper::uninit_{ |
26 | &noop_<void, exception_wrapper const*, exception_wrapper*>, |
27 | &noop_<void, exception_wrapper*, exception_wrapper*>, |
28 | &noop_<void, exception_wrapper*>, |
29 | &noop_<void, exception_wrapper const*>, |
30 | &uninit_type_, |
31 | &noop_<std::exception const*, exception_wrapper const*>, |
32 | &noop_<exception_wrapper, exception_wrapper const*>}; |
33 | |
34 | exception_wrapper::VTable const exception_wrapper::ExceptionPtr::ops_{ |
35 | copy_, |
36 | move_, |
37 | delete_, |
38 | throw_, |
39 | type_, |
40 | get_exception_, |
41 | get_exception_ptr_}; |
42 | |
43 | exception_wrapper::VTable const exception_wrapper::SharedPtr::ops_{ |
44 | copy_, |
45 | move_, |
46 | delete_, |
47 | throw_, |
48 | type_, |
49 | get_exception_, |
50 | get_exception_ptr_}; |
51 | |
52 | namespace { |
53 | std::exception const* get_std_exception_(std::exception_ptr eptr) noexcept { |
54 | try { |
55 | std::rethrow_exception(eptr); |
56 | } catch (const std::exception& ex) { |
57 | return &ex; |
58 | } catch (...) { |
59 | return nullptr; |
60 | } |
61 | } |
62 | } // namespace |
63 | |
64 | exception_wrapper exception_wrapper::from_exception_ptr( |
65 | std::exception_ptr const& ptr) noexcept { |
66 | if (!ptr) { |
67 | return exception_wrapper(); |
68 | } |
69 | try { |
70 | std::rethrow_exception(ptr); |
71 | } catch (std::exception& e) { |
72 | return exception_wrapper(std::current_exception(), e); |
73 | } catch (...) { |
74 | return exception_wrapper(std::current_exception()); |
75 | } |
76 | } |
77 | |
78 | exception_wrapper::exception_wrapper(std::exception_ptr ptr) noexcept |
79 | : exception_wrapper{} { |
80 | if (ptr) { |
81 | if (auto e = get_std_exception_(ptr)) { |
82 | LOG(DFATAL) |
83 | << "Performance error: Please construct exception_wrapper with a " |
84 | "reference to the std::exception along with the " |
85 | "std::exception_ptr." ; |
86 | *this = exception_wrapper{std::move(ptr), *e}; |
87 | } else { |
88 | Unknown uk; |
89 | *this = exception_wrapper{ptr, uk}; |
90 | } |
91 | } |
92 | } |
93 | |
94 | [[noreturn]] void exception_wrapper::onNoExceptionError( |
95 | char const* const name) { |
96 | std::ios_base::Init ioinit_; // ensure std::cerr is alive |
97 | std::cerr << "Cannot use `" << name |
98 | << "` with an empty folly::exception_wrapper" << std::endl; |
99 | std::terminate(); |
100 | } |
101 | |
102 | fbstring exceptionStr(exception_wrapper const& ew) { |
103 | return ew.what(); |
104 | } |
105 | |
106 | } // namespace folly |
107 | |