From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2155) id 1E8A73858D39; Fri, 26 Nov 2021 16:06:33 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1E8A73858D39 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Corinna Vinschen To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: get/setrlimit: implement RLIMIT_AS X-Act-Checkin: newlib-cygwin X-Git-Author: Corinna Vinschen X-Git-Refname: refs/heads/master X-Git-Oldrev: f885632f4f00c9a4a75d61f4b42c73554a0691b3 X-Git-Newrev: 1c7384f9d1b692c8b58af4db8c81d2ce0b10ad06 Message-Id: <20211126160633.1E8A73858D39@sourceware.org> Date: Fri, 26 Nov 2021 16:06:33 +0000 (GMT) X-BeenThere: cygwin-cvs@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Cygwin core component git logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 26 Nov 2021 16:06:33 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=1c7384f9d1b692c8b58af4db8c81d2ce0b10ad06 commit 1c7384f9d1b692c8b58af4db8c81d2ce0b10ad06 Author: Corinna Vinschen Date: Fri Nov 26 17:01:28 2021 +0100 Cygwin: get/setrlimit: implement RLIMIT_AS Code based on the idea implemented by the oneTBB project, see https://github.com/oneapi-src/oneTBB Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/cygheap.h | 1 + winsup/cygwin/ntdll.h | 11 ++++-- winsup/cygwin/resource.cc | 86 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index b90c9e84b..252dd414d 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -565,6 +565,7 @@ struct init_cygheap: public mini_cygheap cygheap_user user; user_heap_info user_heap; mode_t umask; + LONG rlim_as_id; unsigned long rlim_core; HANDLE console_h; cwdstuff cwd; diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 0510d833b..f7c427e40 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -1406,19 +1406,21 @@ extern "C" ULONG, PTOKEN_PRIVILEGES, PULONG); NTSTATUS NTAPI NtAllocateLocallyUniqueId (PLUID); NTSTATUS NTAPI NtAllocateUuids (PLARGE_INTEGER, PULONG, PULONG, PUCHAR); + NTSTATUS NTAPI NtAssignProcessToJobObject (HANDLE, HANDLE); NTSTATUS NTAPI NtCancelTimer (HANDLE, PBOOLEAN); NTSTATUS NTAPI NtClose (HANDLE); NTSTATUS NTAPI NtCommitTransaction (HANDLE, BOOLEAN); NTSTATUS NTAPI NtContinue (PCONTEXT, BOOLEAN); NTSTATUS NTAPI NtCreateDirectoryObject (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); - NTSTATUS NTAPI NtCreateKey (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG, - PUNICODE_STRING, ULONG, PULONG); NTSTATUS NTAPI NtCreateEvent (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, EVENT_TYPE, BOOLEAN); NTSTATUS NTAPI NtCreateFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG); + NTSTATUS NTAPI NtCreateJobObject (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); + NTSTATUS NTAPI NtCreateKey (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG, + PUNICODE_STRING, ULONG, PULONG); NTSTATUS NTAPI NtCreateMailslotFile(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG, ULONG, PLARGE_INTEGER); @@ -1478,6 +1480,7 @@ extern "C" NTSTATUS NTAPI NtOpenEvent (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); NTSTATUS NTAPI NtOpenFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG); + NTSTATUS NTAPI NtOpenJobObject (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); NTSTATUS NTAPI NtOpenKey (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); NTSTATUS NTAPI NtOpenMutant (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); NTSTATUS NTAPI NtOpenProcessToken (HANDLE, ACCESS_MASK, PHANDLE); @@ -1505,6 +1508,8 @@ extern "C" PFILE_NETWORK_OPEN_INFORMATION); NTSTATUS NTAPI NtQueryInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); + NTSTATUS NTAPI NtQueryInformationJobObject (HANDLE, JOBOBJECTINFOCLASS, + PVOID, ULONG, PULONG); NTSTATUS NTAPI NtQueryInformationProcess (HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); NTSTATUS NTAPI NtQueryInformationThread (HANDLE, THREADINFOCLASS, PVOID, @@ -1542,6 +1547,8 @@ extern "C" NTSTATUS NTAPI NtSetEvent (HANDLE, PULONG); NTSTATUS NTAPI NtSetInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); + NTSTATUS NTAPI NtSetInformationJobObject (HANDLE, JOBOBJECTINFOCLASS, PVOID, + ULONG); NTSTATUS NTAPI NtSetInformationThread (HANDLE, THREADINFOCLASS, PVOID, ULONG); NTSTATUS NTAPI NtSetInformationToken (HANDLE, TOKEN_INFORMATION_CLASS, PVOID, ULONG); diff --git a/winsup/cygwin/resource.cc b/winsup/cygwin/resource.cc index 1664bca0f..9a3cc21b8 100644 --- a/winsup/cygwin/resource.cc +++ b/winsup/cygwin/resource.cc @@ -20,6 +20,7 @@ details. */ #include "pinfo.h" #include "dtable.h" #include "cygheap.h" +#include "shared_info.h" #include "ntdll.h" /* add timeval values */ @@ -162,6 +163,15 @@ get_rlimit_stack (void) return (size_t) rl.rlim_cur; } +static LONG job_serial_number __attribute__((section (".cygwin_dll_common"), shared)); + +static PWCHAR +job_shared_name (PWCHAR buf, LONG num) +{ + __small_swprintf (buf, L"rlimit.%d", num); + return buf; +} + extern "C" int getrlimit (int resource, struct rlimit *rlp) { @@ -175,7 +185,36 @@ getrlimit (int resource, struct rlimit *rlp) case RLIMIT_CPU: case RLIMIT_FSIZE: case RLIMIT_DATA: + break; case RLIMIT_AS: + { + UNICODE_STRING uname; + WCHAR jobname[32]; + OBJECT_ATTRIBUTES attr; + HANDLE job = NULL; + NTSTATUS status; + JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobinfo; + + if (cygheap->rlim_as_id) + { + RtlInitUnicodeString (&uname, + job_shared_name (jobname, + cygheap->rlim_as_id)); + InitializeObjectAttributes (&attr, &uname, 0, + get_session_parent_dir (), NULL); + /* May fail, just check NULL job in that case. */ + NtOpenJobObject (&job, JOB_OBJECT_QUERY, &attr); + } + status = NtQueryInformationJobObject (job, + JobObjectExtendedLimitInformation, + &jobinfo, sizeof jobinfo, NULL); + if (!NT_SUCCESS (status)) + break; + if (jobinfo.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PROCESS_MEMORY) + rlp->rlim_cur = rlp->rlim_max = jobinfo.ProcessMemoryLimit; + if (job) + NtClose (job); + } break; case RLIMIT_STACK: __get_rlimit_stack (rlp); @@ -222,6 +261,53 @@ setrlimit (int resource, const struct rlimit *rlp) switch (resource) { + case RLIMIT_AS: + { + LONG new_as_id = 0; + UNICODE_STRING uname; + WCHAR jobname[32]; + OBJECT_ATTRIBUTES attr; + NTSTATUS status = STATUS_SUCCESS; + HANDLE job = NULL; + JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobinfo = { 0 }; + + /* If we already have a limit, we must not change it because that + would potentially influence already running child processes. + Just try to create another, nested job. On systems prior to + Windows 8 / Server 2012 this will fail, but that's ok. */ + while (new_as_id == 0) + new_as_id = InterlockedIncrement (&job_serial_number); + RtlInitUnicodeString (&uname, + job_shared_name (jobname, new_as_id)); + InitializeObjectAttributes (&attr, &uname, 0, + get_session_parent_dir (), NULL); + status = NtCreateJobObject (&job, JOB_OBJECT_ALL_ACCESS, &attr); + if (!NT_SUCCESS (status)) + { + __seterrno_from_nt_status (status); + __leave; + } + status = NtAssignProcessToJobObject (job, NtCurrentProcess ()); + if (NT_SUCCESS (status)) + { + jobinfo.BasicLimitInformation.LimitFlags + = JOB_OBJECT_LIMIT_PROCESS_MEMORY; + /* Per Linux man page, round down to system pagesize. */ + jobinfo.ProcessMemoryLimit + = rounddown (rlp->rlim_cur, wincap.allocation_granularity ()); + status = NtSetInformationJobObject (job, + JobObjectExtendedLimitInformation, + &jobinfo, sizeof jobinfo); + } + NtClose (job); + if (!NT_SUCCESS (status)) + { + __seterrno_from_nt_status (status); + __leave; + } + cygheap->rlim_as_id = new_as_id; + } + break; case RLIMIT_CORE: cygheap->rlim_core = rlp->rlim_cur; break;