Skip to content

Commit 0776b75

Browse files
khanelimanAlexays
authored andcommitted
fix(util): keep GLib child setup fork-safe
Move WAYBAR_OUTPUT_NAME injection into the parent-provided spawn environment and strip logging and setenv() out of the GLib child-setup hook. That keeps the helper's post-fork path limited to the process setup it actually needs, which is a safer fit for sanitizer-heavy platforms such as FreeBSD. Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
1 parent 2547dd6 commit 0776b75

1 file changed

Lines changed: 30 additions & 20 deletions

File tree

src/util/command_line_stream.cpp

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,33 +23,42 @@
2323

2424
namespace {
2525

26-
void prepareChild(const std::string& output_name) {
26+
auto buildChildEnvironment(const std::string& output_name) -> std::vector<std::string> {
27+
auto names = Glib::listenv();
28+
std::vector<std::string> envp;
29+
envp.reserve(names.size() + 1);
30+
31+
for (const auto& name : names) {
32+
bool found = false;
33+
auto value = Glib::getenv(name, found);
34+
if (!found || name == "WAYBAR_OUTPUT_NAME") {
35+
continue;
36+
}
37+
envp.push_back(name + "=" + value);
38+
}
39+
40+
if (!output_name.empty()) {
41+
envp.push_back("WAYBAR_OUTPUT_NAME=" + output_name);
42+
}
43+
44+
return envp;
45+
}
46+
47+
void prepareChild() {
2748
sigset_t mask;
2849
sigfillset(&mask);
2950

30-
const auto err = pthread_sigmask(SIG_UNBLOCK, &mask, nullptr);
31-
if (err != 0) {
32-
spdlog::error("pthread_sigmask in LineStream failed: {}", std::strerror(err));
33-
}
51+
(void)pthread_sigmask(SIG_UNBLOCK, &mask, nullptr);
3452

3553
int deathsig = SIGTERM;
3654
#ifdef __linux__
37-
if (prctl(PR_SET_PDEATHSIG, deathsig) != 0) {
38-
spdlog::error("prctl(PR_SET_PDEATHSIG) in LineStream failed: {}", std::strerror(errno));
39-
}
55+
(void)prctl(PR_SET_PDEATHSIG, deathsig);
4056
#endif
4157
#ifdef __FreeBSD__
42-
if (procctl(P_PID, 0, PROC_PDEATHSIG_CTL, reinterpret_cast<void*>(&deathsig)) == -1) {
43-
spdlog::error("procctl(PROC_PDEATHSIG_CTL) in LineStream failed: {}", std::strerror(errno));
44-
}
58+
(void)procctl(P_PID, 0, PROC_PDEATHSIG_CTL, reinterpret_cast<void*>(&deathsig));
4559
#endif
4660

47-
if (setpgid(0, 0) != 0) {
48-
spdlog::error("setpgid in LineStream failed: {}", std::strerror(errno));
49-
}
50-
if (!output_name.empty()) {
51-
setenv("WAYBAR_OUTPUT_NAME", output_name.c_str(), 1);
52-
}
61+
(void)setpgid(0, 0);
5362
}
5463

5564
void emitBufferedLines(std::string& buffer,
@@ -91,9 +100,10 @@ void waybar::util::command::LineStream::start(const std::string& cmd) {
91100
stop();
92101

93102
std::vector<std::string> argv{"/bin/sh", "-c", cmd};
94-
Glib::spawn_async_with_pipes("", argv, Glib::SPAWN_DO_NOT_REAP_CHILD | Glib::SPAWN_CLOEXEC_PIPES,
95-
sigc::bind(sigc::ptr_fun(&prepareChild), output_name_), &pid_,
96-
nullptr, &stdout_fd_, nullptr);
103+
auto envp = buildChildEnvironment(output_name_);
104+
Glib::spawn_async_with_pipes("", argv, envp,
105+
Glib::SPAWN_DO_NOT_REAP_CHILD | Glib::SPAWN_CLOEXEC_PIPES,
106+
sigc::ptr_fun(&prepareChild), &pid_, nullptr, &stdout_fd_, nullptr);
97107

98108
const auto flags = fcntl(stdout_fd_, F_GETFL, 0);
99109
if (flags == -1 || fcntl(stdout_fd_, F_SETFL, flags | O_NONBLOCK) == -1) {

0 commit comments

Comments
 (0)