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

View File

@ -40,7 +40,7 @@ namespace ipc {
* Construct ipc handler * Construct ipc handler
*/ */
ipc::ipc(signal_emitter& emitter, const logger& logger, loop& loop) 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())); 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) { 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.info("Opening ipc socket at '%s'", sock_path);
m_log.notice("Listening for IPC messages (PID: %d)", getpid()); m_log.notice("Listening for IPC messages (PID: %d)", getpid());
socket->bind(sock_path); m_socket->bind(sock_path);
socket->listen( m_socket->listen(
4, [this]() { on_connection(); }, 4, [this]() { on_connection(); },
[this](const auto& e) { [this](const auto& e) {
m_log.err("libuv error while listening to IPC socket: %s", uv_strerror(e.status)); 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; auto& c = *connection;
socket->accept(*c.client_pipe); m_socket->accept(*c.client_pipe);
c.client_pipe->read_start( c.client_pipe->read_start(
[this, &c](const auto& e) { [this, &c](const auto& e) {
try { 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) { } catch (const decoder::error& e) {
m_log.err("ipc: Failed to decode IPC message (reason: %s)", e.what()); 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>()) { 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) { if ((fd = open(path.c_str(), O_RDONLY | O_NONBLOCK)) == -1) {
throw system_error("Failed to open pipe '" + path + "'"); throw system_error("Failed to open pipe '" + path + "'");
} }
@ -196,7 +196,7 @@ namespace ipc {
/** /**
* Receive parts of an IPC message * Receive parts of an IPC message
*/ */
void ipc::receive_data(string buf) { void ipc::receive_data(const string& buf) {
m_pipe_buffer += 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); 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. * 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>(); auto conn = loop.handle<PipeHandle>();
conn->connect( conn->connect(
channel, channel,
[&conn, &decoders, pid, type, payload, channel, idx]() { [&handle = *conn, &decoders, pid, type, payload, channel, idx]() {
on_connection(*conn, decoders[idx], pid, type, payload); on_connection(handle, decoders[idx], pid, type, payload);
}, },
[&](const auto& e) { [&](const auto& e) {
fprintf(stderr, "%s: Failed to connect to '%s' (err: '%s')\n", exec, channel.c_str(), uv_strerror(e.status)); fprintf(stderr, "%s: Failed to connect to '%s' (err: '%s')\n", exec, channel.c_str(), uv_strerror(e.status));