Skip to content

Commit 441412a

Browse files
authored
fix error handling in ipc client and add safety checks (#337)
* fix erroring out if ipc is not available and add safety checks if ipc isn’t available on language widget, don’t render it fixes #336 * uncrustify * clean up headers * print socket path on error
1 parent b5e84c8 commit 441412a

4 files changed

Lines changed: 70 additions & 45 deletions

File tree

src/panel/panel.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,15 @@ class WayfirePanel::impl
200200

201201
if (name == "language")
202202
{
203-
return Widget(new WayfireLanguage());
203+
if (WayfireIPC::get_instance()->connected)
204+
{
205+
return Widget(new WayfireLanguage());
206+
} else
207+
{
208+
std::cerr << "Wayfire IPC not connected, which is required to load language widget." <<
209+
std::endl;
210+
return nullptr;
211+
}
204212
}
205213

206214
if (auto pixel = widget_with_value(name, "spacing"))

src/panel/widgets/language.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <iostream>
12
#include <cstddef>
23
#include <cstdint>
34

@@ -25,6 +26,13 @@ void WayfireLanguage::init(Gtk::Box *container)
2526
ipc_client->subscribe(this, {"keyboard-modifier-state-changed"});
2627
ipc_client->send("{\"method\":\"wayfire/get-keyboard-state\"}", [=] (wf::json_t data)
2728
{
29+
if (data.serialize().find(
30+
"error") != std::string::npos)
31+
{
32+
std::cerr << "Error getting keyboard state for language widget. Is wayfire ipc-rules plugin enabled?" << std::endl;
33+
return;
34+
}
35+
2836
set_available(data["possible-layouts"]);
2937
set_current(data["layout-index"]);
3038
});

src/util/wf-ipc.cpp

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,70 @@
1+
#include <sys/socket.h>
2+
#include <sys/un.h>
3+
#include <unistd.h>
4+
#include <poll.h>
5+
6+
#include <sigc++/functors/mem_fun.h>
7+
#include <iostream>
18
#include <cstdint>
29
#include <cstdlib>
3-
#include <fcntl.h>
4-
#include <functional>
5-
#include <giomm/enums.h>
6-
#include <glibmm/iochannel.h>
710
#include <memory>
811
#include <optional>
9-
#include <stdexcept>
10-
#include <string>
1112
#include <string_view>
12-
#include <sys/socket.h>
13-
#include <sys/un.h>
14-
#include <unistd.h>
15-
#include <poll.h>
16-
#include <vector>
17-
#include <wayfire/nonstd/json.hpp>
13+
1814
#include <wayfire/util/log.hpp>
1915

2016
#include "wf-ipc.hpp"
21-
#include "giomm/cancellable.h"
22-
#include "giomm/error.h"
23-
#include "giomm/socketclient.h"
24-
#include "giomm/unixsocketaddress.h"
25-
#include "glibconfig.h"
26-
#include "glibmm/error.h"
27-
#include "glibmm/iochannel.h"
28-
#include "glibmm/main.h"
29-
#include "sigc++/functors/mem_fun.h"
3017

3118
WayfireIPC::WayfireIPC()
3219
{
33-
connect();
20+
if (connect())
21+
{
22+
sig_connection = Glib::signal_io().connect(
23+
sigc::mem_fun(*this, &WayfireIPC::receive),
24+
connection->get_socket()->get_fd(),
25+
Glib::IOCondition::IO_IN);
3426

35-
sig_connection = Glib::signal_io().connect(
36-
sigc::mem_fun(*this, &WayfireIPC::receive),
37-
connection->get_socket()->get_fd(),
38-
Glib::IOCondition::IO_IN);
27+
connected = true;
28+
} else
29+
{
30+
std::cerr << "Failed to connect to WAYFIRE_SOCKET. Is wayfire ipc plugin enabled?" << std::endl;
31+
}
3932
}
4033

4134
WayfireIPC::~WayfireIPC()
4235
{
43-
disconnect();
36+
if (connected)
37+
{
38+
disconnect();
39+
}
4440
}
4541

46-
void WayfireIPC::connect()
42+
bool WayfireIPC::connect()
4743
{
4844
const char *socket_path = getenv("WAYFIRE_SOCKET");
49-
if (socket_path == nullptr)
45+
if (!socket_path || std::string(socket_path).empty())
46+
{
47+
std::cerr << "Wayfire socket not found" << std::endl;
48+
return false;
49+
}
50+
51+
try {
52+
auto client = Gio::SocketClient::create();
53+
auto address = Gio::UnixSocketAddress::create(socket_path);
54+
connection = client->connect(address);
55+
connection->get_socket()->set_blocking(false);
56+
output = connection->get_output_stream();
57+
input = connection->get_input_stream();
58+
cancel = Gio::Cancellable::create();
59+
60+
return true;
61+
} catch (const Glib::Error& ex)
5062
{
51-
throw std::runtime_error("Wayfire socket not found");
63+
std::cerr << "Error connecting to WAYFIRE_SOCKET at path \"" << socket_path << "\": " << ex.what();
64+
return false;
5265
}
5366

54-
auto client = Gio::SocketClient::create();
55-
auto address = Gio::UnixSocketAddress::create(socket_path);
56-
connection = client->connect(address);
57-
connection->get_socket()->set_blocking(false);
58-
output = connection->get_output_stream();
59-
input = connection->get_input_stream();
60-
cancel = Gio::Cancellable::create();
67+
return false;
6168
}
6269

6370
void WayfireIPC::disconnect()

src/util/wf-ipc.hpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
#pragma once
22

3-
#include <giomm/cancellable.h>
4-
#include <giomm/outputstream.h>
5-
#include <giomm/socketconnection.h>
6-
#include <glibmm/iochannel.h>
7-
#include <glibmm/refptr.h>
8-
#include <wayfire/nonstd/json.hpp>
3+
#include <glibmm.h>
4+
#include <giomm.h>
5+
96
#include <sigc++/connection.h>
107
#include <functional>
118
#include <memory>
@@ -15,6 +12,8 @@
1512
#include <unordered_map>
1613
#include <vector>
1714

15+
#include <wayfire/nonstd/json.hpp>
16+
1817
class IIPCSubscriber
1918
{
2019
public:
@@ -26,6 +25,7 @@ using response_handler = std::function<void (wf::json_t)>;
2625
class WayfireIPC;
2726
class IPCClient
2827
{
28+
private:
2929
int id;
3030
std::shared_ptr<WayfireIPC> ipc;
3131
std::queue<response_handler> response_handlers;
@@ -44,6 +44,7 @@ class IPCClient
4444

4545
class WayfireIPC : public std::enable_shared_from_this<WayfireIPC>
4646
{
47+
private:
4748
std::queue<int> response_handlers;
4849
std::set<IIPCSubscriber*> subscribers;
4950
std::unordered_map<std::string, std::set<IIPCSubscriber*>> subscriptions;
@@ -57,7 +58,7 @@ class WayfireIPC : public std::enable_shared_from_this<WayfireIPC>
5758
std::queue<std::string> write_queue;
5859
bool writing = false;
5960

60-
void connect();
61+
bool connect();
6162
void disconnect();
6263
void send_message(const std::string& message);
6364
bool send_queue(Glib::IOCondition cond);
@@ -75,6 +76,7 @@ class WayfireIPC : public std::enable_shared_from_this<WayfireIPC>
7576
void client_destroyed(int id);
7677

7778
static std::shared_ptr<WayfireIPC> get_instance();
79+
bool connected = false;
7880
WayfireIPC();
7981
~WayfireIPC();
8082
};

0 commit comments

Comments
 (0)