Skip to content

Commit ba1ce30

Browse files
Avoid throwing exceptions for -fno-exceptions builds
1 parent 72d0ed9 commit ba1ce30

File tree

4 files changed

+98
-124
lines changed

4 files changed

+98
-124
lines changed

libcxx/src/stacktrace/tools/tools.cpp

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -48,70 +48,118 @@ _LIBCPP_HIDE_FROM_ABI base::str u64_string(base& base, uintptr_t __val) {
4848
# define STRINGIFY0(x) #x
4949
# define STRINGIFY(x) STRINGIFY0(x)
5050

51-
void try_tools(base& base, function<bool(tool const&)> cb) {
51+
bool try_tools(base& base, function<bool(tool const&)> cb) {
5252
char const* prog_name;
5353

5454
if ((prog_name = getenv("LIBCXX_STACKTRACE_FORCE_LLVM_SYMBOLIZER_PATH"))) {
5555
if (cb(llvm_symbolizer{base, prog_name})) {
56-
return;
56+
return true;
5757
}
5858
} else {
5959
# if defined(LIBCXX_STACKTRACE_FORCE_LLVM_SYMBOLIZER_PATH)
6060
if (cb(llvm_symbolizer{base, STRINGIFY(LIBCXX_STACKTRACE_FORCE_LLVM_SYMBOLIZER_PATH)})) {
61-
return;
61+
return true;
6262
}
6363
# else
6464
if (cb(llvm_symbolizer{base})) {
65-
return;
65+
return true;
6666
}
6767
# endif
6868
}
6969

7070
if ((prog_name = getenv("LIBCXX_STACKTRACE_FORCE_GNU_ADDR2LINE_PATH"))) {
7171
if (cb(addr2line{base, prog_name})) {
72-
return;
72+
return true;
7373
}
7474
} else {
7575
# if defined(LIBCXX_STACKTRACE_FORCE_GNU_ADDR2LINE_PATH)
7676
if (cb(addr2line{base, STRINGIFY(LIBCXX_STACKTRACE_FORCE_GNU_ADDR2LINE_PATH)})) {
77-
return;
77+
return true;
7878
}
7979
# else
8080
if (cb(addr2line{base})) {
81-
return;
81+
return true;
8282
}
8383
# endif
8484
}
8585

8686
if ((prog_name = getenv("LIBCXX_STACKTRACE_FORCE_APPLE_ATOS_PATH"))) {
8787
if (cb(atos{base, prog_name})) {
88-
return;
88+
return true;
8989
}
9090
} else {
9191
# if defined(LIBCXX_STACKTRACE_FORCE_APPLE_ATOS_PATH)
9292
if (cb(atos{base, STRINGIFY(LIBCXX_STACKTRACE_FORCE_APPLE_ATOS_PATH)})) {
93-
return;
93+
return true;
9494
}
9595
# else
9696
if (cb(atos{base})) {
97-
return;
97+
return true;
9898
}
9999
# endif
100100
}
101+
102+
return false; // nothing succeeded
101103
}
102104

103105
} // namespace
104106

105-
void spawner::resolve_lines() {
106-
try_tools(base_, [&](tool const& prog) {
107+
bool file_actions::initFileActions() {
108+
if (!fa_initialized_) {
109+
if (posix_spawn_file_actions_init(&fa_)) {
110+
return false;
111+
}
112+
fa_initialized_ = true;
113+
}
114+
return true;
115+
}
116+
117+
file_actions::~file_actions() { posix_spawn_file_actions_destroy(&fa_); }
118+
119+
bool file_actions::addClose(int fd) { return initFileActions() && (posix_spawn_file_actions_addclose(&fa_, fd) == 0); }
120+
121+
bool file_actions::addDup2(int fd, int std_fd) {
122+
return initFileActions() && (posix_spawn_file_actions_adddup2(&fa_, fd, std_fd) == 0);
123+
}
124+
125+
fd file_actions::redirectOutFD() {
126+
int fds[2];
127+
if (::pipe(fds)) {
128+
return {}; // return invalid FD
129+
}
130+
addClose(fds[0]);
131+
addDup2(fds[1], 1);
132+
return {fds[0]};
133+
}
134+
135+
pspawn::~pspawn() {
136+
if (pid_) {
137+
kill(pid_, SIGTERM);
138+
wait();
139+
}
140+
}
141+
142+
bool pspawn::spawn(base::list<base::str> const& argStrings) {
143+
base::vec<char const*> argv = tool_.base_.make_vec<char const*>();
144+
argv.reserve(argStrings.size() + 1);
145+
for (auto const& str : argStrings) {
146+
argv.push_back(str.data());
147+
}
148+
argv.push_back(nullptr);
149+
return posix_spawnp(&pid_, argv[0], &fa_.fa_, nullptr, const_cast<char**>(argv.data()), nullptr) == 0;
150+
}
151+
152+
int pspawn::wait() {
153+
int status;
154+
waitpid(pid_, &status, 0);
155+
return status;
156+
}
157+
158+
bool spawner::resolve_lines() {
159+
return try_tools(base_, [&](tool const& prog) {
107160
char buf[512];
108161
pspawn_tool proc(prog, base_, buf, sizeof(buf));
109-
try {
110-
proc.run();
111-
return true;
112-
} catch (failed const& failed) {
113-
}
114-
return false;
162+
return proc.run();
115163
});
116164
}
117165

@@ -170,7 +218,7 @@ Note that this includes an extra empty line as a terminator.
170218
line.pop_back();
171219
}
172220
if (line.empty()) {
173-
return;
221+
return; // done
174222
}
175223
if (!line.starts_with(" ")) {
176224
// The symbol has no leading whitespace, while the other

libcxx/src/stacktrace/tools/tools.h

Lines changed: 26 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include <cstddef>
1818
#include <cstdlib>
1919
#include <spawn.h>
20-
#include <string>
2120
#include <sys/fcntl.h>
2221
#include <sys/types.h>
2322
#include <sys/wait.h>
@@ -27,7 +26,6 @@
2726
#include <__stacktrace/basic.h>
2827
#include <__stacktrace/entry.h>
2928

30-
#include "stacktrace/utils/failed.h"
3129
#include "stacktrace/utils/fd.h"
3230

3331
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -74,73 +72,29 @@ struct atos : tool {
7472

7573
struct file_actions {
7674
posix_spawn_file_actions_t fa_;
75+
bool fa_initialized_{false};
7776

78-
file_actions() {
79-
if (posix_spawn_file_actions_init(&fa_)) {
80-
throw failed("posix_spawn_file_actions_init", errno);
81-
}
82-
}
77+
~file_actions();
8378

84-
~file_actions() { posix_spawn_file_actions_destroy(&fa_); }
79+
bool initFileActions();
80+
bool addClose(int fd);
81+
bool addDup2(int fd, int std_fd);
8582

86-
void addClose(int fd) {
87-
if (posix_spawn_file_actions_addclose(&fa_, fd)) {
88-
throw failed("posix_spawn_file_actions_addclose", errno);
89-
}
90-
}
91-
void addDup2(int fd, int stdfd) {
92-
if (posix_spawn_file_actions_adddup2(&fa_, fd, stdfd)) {
93-
throw failed("posix_spawn_file_actions_adddup2", errno);
94-
}
95-
}
96-
97-
fd redirectOutFD() {
98-
int fds[2];
99-
if (::pipe(fds)) {
100-
throw failed("pipe", errno);
101-
}
102-
addClose(fds[0]);
103-
addDup2(fds[1], 1);
104-
return {fds[0]};
105-
}
106-
107-
void redirectInNull() { addDup2(fd::null_fd(), 0); }
108-
void redirectOutNull() { addDup2(fd::null_fd(), 1); }
109-
void redirectErrNull() { addDup2(fd::null_fd(), 2); }
83+
fd redirectOutFD();
84+
bool redirectInNull() { return addDup2(fd::null_fd(), 0); }
85+
bool redirectOutNull() { return addDup2(fd::null_fd(), 1); }
86+
bool redirectErrNull() { return addDup2(fd::null_fd(), 2); }
11087
};
11188

11289
struct pspawn {
11390
tool const& tool_;
11491
pid_t pid_{0};
11592
file_actions fa_{};
11693

117-
// TODO(stacktrace23): ignore SIGCHLD for spawned subprocess
94+
~pspawn();
11895

119-
~pspawn() {
120-
if (pid_) {
121-
kill(pid_, SIGTERM);
122-
wait();
123-
}
124-
}
125-
126-
void spawn(base::list<base::str> const& argStrings) {
127-
base::vec<char const*> argv = tool_.base_.make_vec<char const*>();
128-
argv.reserve(argStrings.size() + 1);
129-
for (auto const& str : argStrings) {
130-
argv.push_back(str.data());
131-
}
132-
argv.push_back(nullptr);
133-
int err;
134-
if ((err = posix_spawnp(&pid_, argv[0], &fa_.fa_, nullptr, const_cast<char**>(argv.data()), nullptr))) {
135-
throw failed("posix_spawnp", err);
136-
}
137-
}
138-
139-
int wait() {
140-
int status;
141-
waitpid(pid_, &status, 0);
142-
return status;
143-
}
96+
bool spawn(base::list<base::str> const& argStrings);
97+
int wait();
14498
};
14599

146100
struct pspawn_tool : pspawn {
@@ -155,29 +109,36 @@ struct pspawn_tool : pspawn {
155109
fa_.redirectInNull();
156110
}
157111

158-
void run() {
159-
// Cannot run "addr2line" or similar without addresses, since we
160-
// provide them in argv, and if there are none passed in argv, the
161-
// tool will try to read from stdin and hang.
112+
bool run() {
113+
// Cannot run "addr2line" or similar without addresses, since we provide them in argv,
114+
// and if there are none passed in argv, the tool will try to read from stdin and hang.
115+
// Nothing to do, so return true for "success".
162116
if (base_.__entries_.empty()) {
163-
return;
117+
return true;
118+
}
119+
120+
if (!fd_) {
121+
return false;
164122
}
165123

166124
auto argStrings = tool_.buildArgs(base_);
167-
spawn(argStrings);
125+
if (!spawn(argStrings)) {
126+
return false;
127+
}
168128

169129
auto end = base_.__entries_.end();
170130
auto it = base_.__entries_.begin();
171131
while (it != end) {
172132
auto& entry = (entry_base&)(*it++);
173133
tool_.parseOutput(base_, entry, stream_);
174134
}
135+
return true;
175136
}
176137
};
177138

178139
struct spawner {
179140
base& base_;
180-
void resolve_lines();
141+
bool resolve_lines();
181142
};
182143

183144
} // namespace __stacktrace

libcxx/src/stacktrace/utils/failed.h

Lines changed: 0 additions & 31 deletions
This file was deleted.

libcxx/src/stacktrace/utils/fd.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,16 @@
1919
#include <unistd.h>
2020
#include <utility>
2121

22-
#include "stacktrace/utils/failed.h"
23-
2422
_LIBCPP_BEGIN_NAMESPACE_STD
2523
namespace __stacktrace {
2624

2725
/** Encapsulates a plain old file descriptor `int`. Avoids copies in order to
2826
force some component to "own" this, although it's freely convertible back to
2927
integer form. Default-constructed, closed, and moved-out-of instances will have
3028
the invalid fd `-1`. */
31-
class _LIBCPP_HIDE_FROM_ABI fd {
29+
struct _LIBCPP_HIDE_FROM_ABI fd {
3230
int fd_{-1};
3331

34-
public:
3532
fd() : fd(-1) {}
3633
fd(int fdint) : fd_(fdint) {}
3734

@@ -73,20 +70,19 @@ class _LIBCPP_HIDE_FROM_ABI fd {
7370
};
7471

7572
/** Wraps a readable fd using the `streambuf` interface. I/O errors arising
76-
from reading the provided fd will result in a `Failed` being thrown. */
73+
from reading the provided fd will result in EOF. */
7774
struct _LIBCPP_HIDE_FROM_ABI fd_streambuf final : std::streambuf {
7875
fd& fd_;
7976
char* buf_;
8077
size_t size_;
78+
8179
_LIBCPP_HIDE_FROM_ABI fd_streambuf(fd& fd, char* buf, size_t size) : fd_(fd), buf_(buf), size_(size) {}
8280
_LIBCPP_HIDE_FROM_ABI virtual ~fd_streambuf() = default;
8381

8482
_LIBCPP_HIDE_FROM_ABI int underflow() override {
8583
int bytesRead = ::read(fd_, buf_, size_);
86-
if (bytesRead < 0) {
87-
throw ::std::__stacktrace::failed("I/O error reading from child process", errno);
88-
}
89-
if (bytesRead == 0) {
84+
if (bytesRead <= 0) {
85+
// error or EOF: return eof to stop
9086
return traits_type::eof();
9187
}
9288
setg(buf_, buf_, buf_ + bytesRead);

0 commit comments

Comments
 (0)