Skip to content

Commit 580d334

Browse files
committed
Fix IPC socket connection race condition on Linux
1 parent c998e31 commit 580d334

1 file changed

Lines changed: 33 additions & 36 deletions

File tree

webview/platform/linux/webview_linux_webkitgtk.cpp

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
#include <QtQuickWidgets/QQuickWidget>
3131
#endif // DESKTOP_APP_WEBVIEW_WAYLAND_COMPOSITOR
3232

33+
#if __has_include(<giounix/giounix.hpp>)
34+
#include <giounix/giounix.hpp>
35+
#endif // __has_include(<giounix/giounix.hpp>)
3336
#include <webview/webview.hpp>
3437
#include <crl/crl.h>
3538
#include <rpl/rpl.h>
@@ -1029,11 +1032,27 @@ void Instance::resize(int w, int h) {
10291032
void Instance::startProcess() {
10301033
auto loop = GLib::MainLoop::new_();
10311034

1032-
auto serviceProcess = Gio::Subprocess::new_({
1035+
auto serviceLauncher = Gio::SubprocessLauncher::new_(
1036+
Gio::SubprocessFlags::NONE_);
1037+
1038+
int pipefd[2]{};
1039+
GError *error = nullptr;
1040+
if (!g_unix_open_pipe(pipefd, O_CLOEXEC, &error)) {
1041+
LOG(("WebView Error: %1").arg(error->message));
1042+
g_clear_error(&error);
1043+
return;
1044+
}
1045+
1046+
serviceLauncher.take_fd(pipefd[0], 3);
1047+
auto pipeGuard = std::make_optional(gsl::finally([&] {
1048+
GLib::close(pipefd[1]);
1049+
}));
1050+
1051+
auto serviceProcess = serviceLauncher.spawnv({
10331052
::base::Integration::Instance().executablePath().toStdString(),
10341053
std::string("-webviewhelper"),
10351054
SocketPath,
1036-
}, Gio::SubprocessFlags::NONE_);
1055+
});
10371056

10381057
if (!serviceProcess) {
10391058
LOG(("WebView Error: %1").arg(
@@ -1140,6 +1159,7 @@ void Instance::startProcess() {
11401159
loop.quit();
11411160
});
11421161

1162+
pipeGuard.reset();
11431163
loop.run();
11441164
if (timeoutHappened) {
11451165
LOG(("WebView Error: Timed out waiting for WebView helper process."));
@@ -1316,42 +1336,19 @@ int Instance::exec() {
13161336

13171337
auto loop = GLib::MainLoop::new_();
13181338

1319-
const auto socketPath = std::vformat(
1320-
std::string_view(SocketPath),
1321-
std::make_format_args(
1322-
static_cast<const std::string>(std::to_string(getpid()))));
1323-
1324-
if (socketPath.empty()) {
1325-
g_critical("IPC socket path is not set.");
1326-
return 1;
1327-
}
1328-
1329-
{
1330-
auto socketFile = Gio::File::new_for_path(socketPath);
1331-
1332-
auto socketMonitor = socketFile.monitor(Gio::FileMonitorFlags::NONE_);
1333-
if (!socketMonitor) {
1334-
g_critical("%s", socketMonitor.error().message_().c_str());
1335-
return 1;
1336-
}
1337-
1338-
socketMonitor->signal_changed().connect([&](
1339-
Gio::FileMonitor,
1340-
Gio::File file,
1341-
Gio::File otherFile,
1342-
Gio::FileMonitorEvent eventType) {
1343-
if (eventType == Gio::FileMonitorEvent::CREATED_) {
1344-
loop.quit();
1345-
}
1346-
});
1347-
1348-
if (!socketFile.query_exists()) {
1349-
loop.run();
1350-
}
1351-
}
1339+
std::uint8_t dummy{};
1340+
#if __has_include(<giounix/giounix.hpp>)
1341+
GioUnix::InputStream::new_(3, true).read_all(&dummy, 1);
1342+
#else // __has_include(<giounix/giounix.hpp>)
1343+
Gio::UnixInputStream::new_(3, true).read_all(&dummy, 1);
1344+
#endif // !__has_include(<giounix/giounix.hpp>)
13521345

13531346
auto connection = Gio::DBusConnection::new_for_address_sync(
1354-
SocketPathToDBusAddress(socketPath),
1347+
SocketPathToDBusAddress(
1348+
std::vformat(
1349+
std::string_view(SocketPath),
1350+
std::make_format_args(
1351+
static_cast<const std::string>(std::to_string(getpid()))))),
13551352
Gio::DBusConnectionFlags::AUTHENTICATION_CLIENT_);
13561353

13571354
if (!connection) {

0 commit comments

Comments
 (0)