@@ -66,6 +66,7 @@ enum class CompletionType : u8 {
6666 Wake,
6767 Timer,
6868 Notifer,
69+ Process,
6970};
7071
7172struct CompletionPacket {
@@ -101,6 +102,15 @@ struct EventLoopNotifier final : CompletionPacket {
101102 OwnHandle wait_event;
102103};
103104
105+ struct EventLoopProcess final : CompletionPacket {
106+ ~EventLoopProcess () = default ;
107+
108+ OwnHandle process;
109+ pid_t pid;
110+ Function<void (pid_t )> exit_handler;
111+ OwnHandle jobobject;
112+ };
113+
104114struct ThreadData {
105115 static ThreadData* the ()
106116 {
@@ -136,6 +146,7 @@ struct ThreadData {
136146 // These are only used to register and unregister. The event loop doesn't access these.
137147 HashMap<intptr_t , NonnullOwnPtr<EventLoopTimer>> timers;
138148 HashMap<Notifier*, NonnullOwnPtr<EventLoopNotifier>> notifiers;
149+ HashMap<pid_t , NonnullOwnPtr<EventLoopProcess>> processes;
139150
140151 // The wake completion packet is posted to the thread's event loop to wake it.
141152 NonnullOwnPtr<EventLoopWake> wake_data;
@@ -210,6 +221,16 @@ size_t EventLoopImplementationWindows::pump(PumpMode pump_mode)
210221 VERIFY (NT_SUCCESS (status));
211222 continue ;
212223 }
224+ if (packet->type == CompletionType::Process) {
225+ auto * process_data = static_cast <EventLoopProcess*>(packet);
226+ pid_t const process_id = process_data->pid ;
227+ // NOTE: This may seem like the incorrect parameter, but https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_associate_completion_port
228+ // states that this field represents the event type indicator
229+ DWORD const event_type = entry.dwNumberOfBytesTransferred ;
230+ if (reinterpret_cast <intptr_t >(entry.lpOverlapped ) == process_id && (event_type == JOB_OBJECT_MSG_EXIT_PROCESS || event_type == JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS))
231+ process_data->exit_handler (process_id);
232+ continue ;
233+ }
213234 VERIFY_NOT_REACHED ();
214235 }
215236 } else {
@@ -351,6 +372,51 @@ void EventLoopManagerWindows::unregister_signal([[maybe_unused]] int handler_id)
351372 VERIFY_NOT_REACHED ();
352373}
353374
375+ void EventLoopManagerWindows::register_process (pid_t pid, ESCAPING Function<void (pid_t )> exit_handler)
376+ {
377+ auto * thread_data = ThreadData::the ();
378+ VERIFY (thread_data);
379+
380+ auto & processes = thread_data->processes ;
381+ if (processes.contains (pid))
382+ return ;
383+
384+ HANDLE process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE , pid);
385+ VERIFY (process_handle);
386+
387+ HANDLE job_object_handle = CreateJobObject (nullptr , nullptr );
388+ VERIFY (job_object_handle);
389+
390+ BOOL succeeded = AssignProcessToJobObject (job_object_handle, process_handle);
391+ VERIFY (succeeded);
392+
393+ auto process_data = make<EventLoopProcess>();
394+ process_data->type = CompletionType::Process;
395+ process_data->process .handle = process_handle;
396+ process_data->pid = pid;
397+ process_data->exit_handler = move (exit_handler);
398+ process_data->jobobject .handle = job_object_handle;
399+
400+ JOBOBJECT_ASSOCIATE_COMPLETION_PORT joacp = { .CompletionKey = process_data.ptr (), .CompletionPort = thread_data->iocp .handle };
401+ succeeded = SetInformationJobObject (job_object_handle, JobObjectAssociateCompletionPortInformation, &joacp, sizeof (JOBOBJECT_ASSOCIATE_COMPLETION_PORT));
402+ VERIFY (succeeded);
403+
404+ processes.set (pid, move (process_data));
405+ }
406+
407+ void EventLoopManagerWindows::unregister_process (pid_t pid)
408+ {
409+ if (auto * thread_data = ThreadData::the ()) {
410+ auto maybe_process = thread_data->processes .take (pid);
411+ if (!maybe_process.has_value ())
412+ return ;
413+ auto process_data = maybe_process.release_value ();
414+ JOBOBJECT_ASSOCIATE_COMPLETION_PORT joacp = { .CompletionKey = process_data, .CompletionPort = nullptr };
415+ BOOL succeeded = SetInformationJobObject (process_data->jobobject .handle , JobObjectAssociateCompletionPortInformation, &joacp, sizeof (JOBOBJECT_ASSOCIATE_COMPLETION_PORT));
416+ VERIFY (succeeded);
417+ }
418+ }
419+
354420void EventLoopManagerWindows::did_post_event ()
355421{
356422}
0 commit comments