When sway's event-subscription send buffer overflows during an event flood, sway closes the client connection. The sway IPC event worker (SleeperThread running handleEvent -> recv) then threw on every iteration and the SleeperThread immediately re-invoked it, leaving the sway modules broken while busy-looping on a dead socket and pegging a CPU. Mirror the niri backend's reconnect loop: on a read/EOF/parse error from the event socket, close the old connection, back off for a couple of seconds (so we don't busy-spin), re-open the socket and replay the same subscriptions, then resume. A running_ flag set at the start of teardown makes the worker bail out cleanly instead of reconnecting to a socket that is being closed on purpose. The IPC message protocol and event parsing are unchanged. Fixes #3166.
63 lines
1.5 KiB
C++
63 lines
1.5 KiB
C++
#pragma once
|
|
|
|
#include <sigc++/sigc++.h>
|
|
|
|
#include <atomic>
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "ipc.hpp"
|
|
#include "util/SafeSignal.hpp"
|
|
#include "util/scoped_fd.hpp"
|
|
#include "util/sleeper_thread.hpp"
|
|
|
|
namespace waybar::modules::sway {
|
|
|
|
class Ipc {
|
|
public:
|
|
Ipc();
|
|
~Ipc();
|
|
|
|
struct ipc_response {
|
|
uint32_t size;
|
|
uint32_t type;
|
|
std::string payload;
|
|
};
|
|
|
|
::waybar::SafeSignal<const struct ipc_response&> signal_event;
|
|
::waybar::SafeSignal<const struct ipc_response&> signal_cmd;
|
|
|
|
void sendCmd(uint32_t type, const std::string& payload = "");
|
|
void subscribe(const std::string& payload);
|
|
void handleEvent();
|
|
void setWorker(std::function<void()>&& func);
|
|
|
|
protected:
|
|
static inline const std::string ipc_magic_ = "i3-ipc";
|
|
static inline const size_t ipc_header_size_ = ipc_magic_.size() + 8;
|
|
|
|
static std::string getSocketPath();
|
|
static int open(const std::string&);
|
|
|
|
struct ipc_response send(int fd, uint32_t type, const std::string& payload = "");
|
|
struct ipc_response recv(int fd);
|
|
|
|
// Re-establish the event socket and re-subscribe after sway drops us, backing
|
|
// off between attempts so we don't busy-loop while sway is unavailable.
|
|
void reconnectEvent();
|
|
|
|
std::string socketPath_;
|
|
std::vector<std::string> subscribed_events_;
|
|
std::atomic<bool> running_{true};
|
|
|
|
util::ScopedFd fd_;
|
|
util::ScopedFd fd_event_;
|
|
std::mutex mutex_;
|
|
util::SleeperThread thread_;
|
|
};
|
|
|
|
} // namespace waybar::modules::sway
|