fix(ipc): Crash when sending to multiple instances

In polybar-msg, the connection handle was captured as a reference to a
shared_ptr, but the shared_ptr went out of scope right after.

This probably always caused UB, but was only noticeable for two or more
instances.
This commit is contained in:
patrick96 2022-10-23 14:11:31 +02:00 committed by Patrick Ziegler
parent 30e1cc2595
commit 291a4844bc
3 changed files with 13 additions and 13 deletions

View File

@ -42,7 +42,7 @@ namespace ipc {
const logger& m_log;
eventloop::loop& m_loop;
eventloop::pipe_handle_t socket;
eventloop::pipe_handle_t m_socket;
class connection : public non_copyable_mixin, public non_movable_mixin {
public:
@ -89,7 +89,7 @@ namespace ipc {
* Buffer for the currently received IPC message over the named pipe
*/
string m_pipe_buffer{};
void receive_data(string buf);
void receive_data(const string& buf);
void receive_eof();
};
} // namespace ipc

View File

@ -40,7 +40,7 @@ namespace ipc {
* Construct ipc handler
*/
ipc::ipc(signal_emitter& emitter, const logger& logger, loop& loop)
: m_sig(emitter), m_log(logger), m_loop(loop), socket(loop.handle<PipeHandle>()) {
: m_sig(emitter), m_log(logger), m_loop(loop), m_socket(loop.handle<PipeHandle>()) {
m_pipe_path = string_util::replace(PATH_MESSAGING_FIFO, "%pid%", to_string(getpid()));
if (file_util::exists(m_pipe_path) && unlink(m_pipe_path.c_str()) == -1) {
@ -57,12 +57,12 @@ namespace ipc {
m_log.info("Opening ipc socket at '%s'", sock_path);
m_log.notice("Listening for IPC messages (PID: %d)", getpid());
socket->bind(sock_path);
socket->listen(
m_socket->bind(sock_path);
m_socket->listen(
4, [this]() { on_connection(); },
[this](const auto& e) {
m_log.err("libuv error while listening to IPC socket: %s", uv_strerror(e.status));
socket->close();
m_socket->close();
});
}
@ -133,12 +133,12 @@ namespace ipc {
});
auto& c = *connection;
socket->accept(*c.client_pipe);
m_socket->accept(*c.client_pipe);
c.client_pipe->read_start(
[this, &c](const auto& e) {
try {
c.dec.on_read((const uint8_t*)e.data, e.len);
c.dec.on_read(reinterpret_cast<const uint8_t*>(e.data), e.len);
} catch (const decoder::error& e) {
m_log.err("ipc: Failed to decode IPC message (reason: %s)", e.what());
@ -175,7 +175,7 @@ namespace ipc {
}
ipc::fifo::fifo(loop& loop, ipc& ipc, const string& path) : pipe_handle(loop.handle<PipeHandle>()) {
int fd;
int fd{};
if ((fd = open(path.c_str(), O_RDONLY | O_NONBLOCK)) == -1) {
throw system_error("Failed to open pipe '" + path + "'");
}
@ -196,7 +196,7 @@ namespace ipc {
/**
* Receive parts of an IPC message
*/
void ipc::receive_data(string buf) {
void ipc::receive_data(const string& buf) {
m_pipe_buffer += buf;
m_log.warn("Using the named pipe at '%s' for ipc is deprecated, always use 'polybar-msg'", m_pipe_path);

View File

@ -260,13 +260,13 @@ int run(int argc, char** argv) {
/*
* Index to decoder is captured because reference can be invalidated due to the vector being modified.
*/
int idx = decoders.size() - 1;
auto idx = decoders.size() - 1;
auto conn = loop.handle<PipeHandle>();
conn->connect(
channel,
[&conn, &decoders, pid, type, payload, channel, idx]() {
on_connection(*conn, decoders[idx], pid, type, payload);
[&handle = *conn, &decoders, pid, type, payload, channel, idx]() {
on_connection(handle, decoders[idx], pid, type, payload);
},
[&](const auto& e) {
fprintf(stderr, "%s: Failed to connect to '%s' (err: '%s')\n", exec, channel.c_str(), uv_strerror(e.status));