Skip to content

Commit 4dda455

Browse files
committed
LibWebView: Implement register_process for Qt Windows event loop
Qt does not use IOCP's in their underlying Windows event loop implementation; however, QWinEventNotifier allows us to register a wait on a process handle that has SYNCHRONIZE access rights. This means an event will be signalled when that process terminates which emits the QWinEventNotifier::activated signal.
1 parent a339c4e commit 4dda455

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

Libraries/LibWebView/EventLoop/EventLoopImplementationQt.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
#include <QSocketNotifier>
2525
#include <QThread>
2626
#include <QTimer>
27+
#if defined(AK_OS_WINDOWS)
28+
# include <AK/Windows.h>
29+
# include <QWinEventNotifier>
30+
#endif
2731

2832
namespace WebView {
2933

@@ -60,6 +64,9 @@ struct ThreadData {
6064

6165
Threading::Mutex mutex;
6266
HashMap<Core::Notifier*, NonnullOwnPtr<QSocketNotifier>> notifiers;
67+
#if defined(AK_OS_WINDOWS)
68+
HashMap<pid_t, QWinEventNotifier*> processes;
69+
#endif
6370
};
6471

6572
class QtEventLoopManagerEvent final : public QEvent {
@@ -382,6 +389,44 @@ void EventLoopManagerQt::unregister_signal(int handler_id)
382389
info.signal_handlers.remove(remove_signal_number);
383390
}
384391

392+
#if defined(AK_OS_WINDOWS)
393+
394+
void EventLoopManagerQt::register_process(pid_t pid, ESCAPING Function<void(pid_t)> handler)
395+
{
396+
HANDLE process_handle = OpenProcess(SYNCHRONIZE, FALSE, pid);
397+
VERIFY(process_handle);
398+
399+
auto* process = new QWinEventNotifier(process_handle);
400+
QObject::connect(process, &QWinEventNotifier::activated, [registered_process_id = pid, registered_process_handler = move(handler), registered_process_handle = process_handle](HANDLE terminated_process_handle) {
401+
if (registered_process_handle == terminated_process_handle) {
402+
registered_process_handler(registered_process_id);
403+
}
404+
});
405+
406+
{
407+
auto& thread_data = ThreadData::the();
408+
Threading::MutexLocker locker(thread_data.mutex);
409+
thread_data.processes.set(pid, process);
410+
}
411+
}
412+
413+
void EventLoopManagerQt::unregister_process(pid_t pid)
414+
{
415+
{
416+
auto& thread_data = ThreadData::the();
417+
Threading::MutexLocker locker(thread_data.mutex);
418+
auto maybe_process = thread_data.processes.take(pid);
419+
if (!maybe_process.has_value())
420+
return;
421+
if (auto* process = maybe_process.release_value()) {
422+
CloseHandle(process->handle());
423+
delete process;
424+
}
425+
}
426+
}
427+
428+
#endif
429+
385430
void EventLoopManagerQt::did_post_event()
386431
{
387432
QCoreApplication::postEvent(m_main_thread_event_target.ptr(), new QtEventLoopManagerEvent(QtEventLoopManagerEvent::process_event_queue_event_type()));

Libraries/LibWebView/EventLoop/EventLoopImplementationQt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ class EventLoopManagerQt final : public Core::EventLoopManager {
3737
virtual int register_signal(int, Function<void(int)>) override;
3838
virtual void unregister_signal(int) override;
3939

40+
#if defined(AK_OS_WINDOWS)
41+
virtual void register_process(pid_t, ESCAPING Function<void(pid_t)> handler) override;
42+
virtual void unregister_process(pid_t pid) override;
43+
#endif
44+
4045
void set_main_loop_signal_notifiers(Badge<EventLoopImplementationQt>);
4146

4247
private:

0 commit comments

Comments
 (0)