1 | /* |
2 | * Copyright 2016-present Facebook, Inc. |
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 | #include <folly/ExceptionWrapper.h> |
17 | |
18 | #include <iostream> |
19 | |
20 | #include <folly/GLog.h> |
21 | |
22 | namespace folly { |
23 | |
24 | exception_wrapper::VTable const exception_wrapper::uninit_{ |
25 | &noop_<void, exception_wrapper const*, exception_wrapper*>, |
26 | &noop_<void, exception_wrapper*, exception_wrapper*>, |
27 | &noop_<void, exception_wrapper*>, |
28 | &noop_<void, exception_wrapper const*>, |
29 | &uninit_type_, |
30 | &noop_<std::exception const*, exception_wrapper const*>, |
31 | &noop_<exception_wrapper, exception_wrapper const*>}; |
32 | |
33 | exception_wrapper::VTable const exception_wrapper::ExceptionPtr::ops_{ |
34 | copy_, |
35 | move_, |
36 | delete_, |
37 | throw_, |
38 | type_, |
39 | get_exception_, |
40 | get_exception_ptr_}; |
41 | |
42 | exception_wrapper::VTable const exception_wrapper::SharedPtr::ops_{ |
43 | copy_, |
44 | move_, |
45 | delete_, |
46 | throw_, |
47 | type_, |
48 | get_exception_, |
49 | get_exception_ptr_}; |
50 | |
51 | namespace { |
52 | std::exception const* get_std_exception_(std::exception_ptr eptr) noexcept { |
53 | try { |
54 | std::rethrow_exception(eptr); |
55 | } catch (const std::exception& ex) { |
56 | return &ex; |
57 | } catch (...) { |
58 | return nullptr; |
59 | } |
60 | } |
61 | } // namespace |
62 | |
63 | exception_wrapper exception_wrapper::from_exception_ptr( |
64 | std::exception_ptr const& ptr) noexcept { |
65 | if (!ptr) { |
66 | return exception_wrapper(); |
67 | } |
68 | try { |
69 | std::rethrow_exception(ptr); |
70 | } catch (std::exception& e) { |
71 | return exception_wrapper(std::current_exception(), e); |
72 | } catch (...) { |
73 | return exception_wrapper(std::current_exception()); |
74 | } |
75 | } |
76 | |
77 | exception_wrapper::exception_wrapper(std::exception_ptr ptr) noexcept |
78 | : exception_wrapper{} { |
79 | if (ptr) { |
80 | if (auto e = get_std_exception_(ptr)) { |
81 | LOG(DFATAL) |
82 | << "Performance error: Please construct exception_wrapper with a " |
83 | "reference to the std::exception along with the " |
84 | "std::exception_ptr." ; |
85 | *this = exception_wrapper{std::move(ptr), *e}; |
86 | } else { |
87 | Unknown uk; |
88 | *this = exception_wrapper{ptr, uk}; |
89 | } |
90 | } |
91 | } |
92 | |
93 | [[noreturn]] void exception_wrapper::onNoExceptionError( |
94 | char const* const name) { |
95 | std::ios_base::Init ioinit_; // ensure std::cerr is alive |
96 | std::cerr << "Cannot use `" << name |
97 | << "` with an empty folly::exception_wrapper" << std::endl; |
98 | std::terminate(); |
99 | } |
100 | |
101 | fbstring exceptionStr(exception_wrapper const& ew) { |
102 | return ew.what(); |
103 | } |
104 | |
105 | } // namespace folly |
106 | |