@@ -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 )> 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->handler (process_id);
232+ continue ;
233+ }
213234 VERIFY_NOT_REACHED ();
214235 }
215236 } else {
@@ -358,6 +379,51 @@ void EventLoopManagerWindows::unregister_signal([[maybe_unused]] int handler_id)
358379 VERIFY_NOT_REACHED ();
359380}
360381
382+ void EventLoopManagerWindows::register_process (pid_t pid, ESCAPING Function<void (pid_t )> handler)
383+ {
384+ auto * thread_data = ThreadData::the ();
385+ VERIFY (thread_data);
386+
387+ auto & processes = thread_data->processes ;
388+ if (processes.contains (pid))
389+ return ;
390+
391+ HANDLE process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE , pid);
392+ VERIFY (process_handle);
393+
394+ HANDLE job_object_handle = CreateJobObject (nullptr , nullptr );
395+ VERIFY (job_object_handle);
396+
397+ BOOL succeeded = AssignProcessToJobObject (job_object_handle, process_handle);
398+ VERIFY (succeeded);
399+
400+ auto process_data = make<EventLoopProcess>();
401+ process_data->type = CompletionType::Process;
402+ process_data->process .handle = process_handle;
403+ process_data->pid = pid;
404+ process_data->handler = move (handler);
405+ process_data->jobobject .handle = job_object_handle;
406+
407+ JOBOBJECT_ASSOCIATE_COMPLETION_PORT joacp = { .CompletionKey = process_data.ptr (), .CompletionPort = thread_data->iocp .handle };
408+ succeeded = SetInformationJobObject (job_object_handle, JobObjectAssociateCompletionPortInformation, &joacp, sizeof (JOBOBJECT_ASSOCIATE_COMPLETION_PORT));
409+ VERIFY (succeeded);
410+
411+ processes.set (pid, move (process_data));
412+ }
413+
414+ void EventLoopManagerWindows::unregister_process (pid_t pid)
415+ {
416+ if (auto * thread_data = ThreadData::the ()) {
417+ auto maybe_process = thread_data->processes .take (pid);
418+ if (!maybe_process.has_value ())
419+ return ;
420+ auto process_data = maybe_process.release_value ();
421+ JOBOBJECT_ASSOCIATE_COMPLETION_PORT joacp = { .CompletionKey = process_data, .CompletionPort = nullptr };
422+ BOOL succeeded = SetInformationJobObject (process_data->jobobject .handle , JobObjectAssociateCompletionPortInformation, &joacp, sizeof (JOBOBJECT_ASSOCIATE_COMPLETION_PORT));
423+ VERIFY (succeeded);
424+ }
425+ }
426+
361427void EventLoopManagerWindows::did_post_event ()
362428{
363429}
0 commit comments