#windows async: detect I/O completion port running full or restrict it to certain job unit events

1 messages · Page 1 of 1 (latest)

fast ivy
#

This article https://devblogs.microsoft.com/oldnewthing/20130405-00/?p=4743 explains how one can wait the complete process tree to be terminated in a Windows job unit, for example after issueing the termination.
However, the docs note https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_associate_completion_port?redirectedfrom=MSDN

Note that, except for limits set with the JobObjectNotificationLimitInformation information class, messages are intended only as notifications and their delivery to the completion port is not guaranteed. The failure of a message to arrive at the completion port does not necessarily mean that the event did not occur. Notifications for limits set with JobObjectNotificationLimitInformation are guaranteed to arrive at the completion port

This sounds like realtime signal queues on posix systems, where signals are dropped, if buffer runs full.
Is there another more reliable notification method for this?

The question is insofar related, as Zig provides for windows CreateIoCompletionPort and I'd like to know conditions for data drops and/or where to find docs on edge case behavior.

A: Besides signaling the processes, the processes may exit in a regular way, which makes the I/O completion port usage necessary https://devblogs.microsoft.com/oldnewthing/20130405-00/?p=4743
but this is not reflected in the docs of WaitForSingleObjectEx:

Waits until the specified object is in the signaled state, an I/O completion routine or asynchronous procedure call (APC) is queued to the thread, or the time-out interval elapses.

However, this does not explain why TerminateJobObject is not applied or not observable in QeryInformationJobObject.
I suspect that Wait does also execute the enqueued job object "things to do" and GetQueuedCompletionStatus does the same.
However, this is not documented.

#

If I dont get replies within ca. 3 days on ideas, I'm assuming that Raymond gave wrong advice on the blog and one should use QueryInformationJobObject JOBOBJECT_BASIC_ACCOUNTING_INFORMATION and compare the active process count against 0.

last glacier
#

Zig may expose the api (because it needed it), but your question is a Windows question, not a zig question.

fast ivy
#

I'm merely exploring the design scope, which is unfortunately very big for process stuff.
You are correct, that the motivation and justification was missing. I've added that.

queen copper
#

Post started with setrlimit then diverged into windows job system stuff. Could you elaborate a bit more on what resource you're trying to limit or get a notification for when it overruns & why?

fast ivy
# queen copper Post started with setrlimit then diverged into windows job system stuff. Could y...

I'm trying to enforce process group memory, process count, processing time and for now the poratble other things possible for eventual usage in a ci library.
https://github.com/matu3ba/sandboxamples/tree/master/test/win
So far I have

    // create job object and set information
    const h_jo = winsec.CreateJobObject(null, null);
    defer std.posix.close(h_jo);
    var jo_eli = std.mem.zeroes(winsec.JOBOBJECT_EXTENDED_LIMIT_INFORMATION);
    jo_eli.BasicLimitInformation.LimitFlags =
        @intFromEnum(winsec.JOB_OBJECT_LIMIT.KILL_ON_JOB_CLOSE) | @intFromEnum(winsec.JOB_OBJECT_LIMIT.JOB_MEMORY) | @intFromEnum(winsec.JOB_OBJECT_LIMIT.ACTIVE_PROCESS) | @intFromEnum(winsec.JOB_OBJECT_LIMIT.JOB_TIME);
    jo_eli.JobMemoryLimit = 20_971_520; // [B] => 20 MB = 20 * (1024)^2 B = 20 * 1_048_576 = 20_971_520 B
    jo_eli.BasicLimitInformation.ActiveProcessLimit = 32;
    jo_eli.BasicLimitInformation.PerJobUserTimeLimit = 1_000 * 1_000 * 10; // 1s = 1_000 * 1_000 * 10 * 100ns
    try winsec.SetInformationJobObject(h_jo, winsec.JobObjectInformationClass.ExtendedLimitInformation, &jo_eli, @sizeOf(@TypeOf(jo_eli)));
    // used via InitializeProcThreadAttributeList, UpdateProcThreadAttribute and STARTUPINFOEXW via EXTENDED_STARTUPINFO_PRESENT
    // of kernel32.CreateProcessW

Also missing is the windows setruid equivalent explained here https://wiki.sei.cmu.edu/confluence/display/c/WIN02-C.+Restrict+privileges+when+spawning+child+processes.

queen copper
#

so limit the amount total memory and new processes one can use/spawn?

fast ivy
#

^ yes.

fast ivy
#

must use wait() to signal process object to process the termination request?!
kinda weird how windows works

fast ivy
#

Justification: As of now, setrlimit of Posix is available and if I remember correctly, Andrew wanted also enforce process limits in the build system, but
as of now, the behavior is not yet available on Windows. Job units are the only way to allow on windows this without requiring system or user modifications,
See https://stackoverflow.com/questions/192876/set-windows-process-or-user-memory-limit.

#

Q: Are there any reliable ways to detect these cases for a (temporary) fallback to polling via JOBOBJECT_BASIC_ACCOUNTING_INFORMATION in QueryInformationJobObject?
A: No, one has to ask the i/o completion queue to do somethiing like executing the enqueue actions on the job object.

fast ivy