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:
parent
30e1cc2595
commit
291a4844bc
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
|
Loading…
Reference in New Issue
Block a user