From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2155) id 43DB0385783E; Tue, 30 Nov 2021 11:56:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 43DB0385783E 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: move RLIMIT_AS handling into static functions X-Act-Checkin: newlib-cygwin X-Git-Author: Corinna Vinschen X-Git-Refname: refs/heads/master X-Git-Oldrev: 670beaed0216aa59603501e8f14e1f04b138bc47 X-Git-Newrev: 3edea7cd55d178164a649d9eea252c807ed2c038 Message-Id: <20211130115614.43DB0385783E@sourceware.org> Date: Tue, 30 Nov 2021 11:56:14 +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: Tue, 30 Nov 2021 11:56:14 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=3edea7cd55d178164a649d9eea252c807ed2c038 commit 3edea7cd55d178164a649d9eea252c807ed2c038 Author: Corinna Vinschen Date: Tue Nov 30 12:54:03 2021 +0100 Cygwin: get/setrlimit: move RLIMIT_AS handling into static functions To keep getrlimit/setrlimit clean, move the RLIMIT_AS code into local static functions __set_rlimit_as and __get_rlimit_as. Also, make adding process to the job the last step, to be able to close and release the job resources if anything failed. Add matching comment. Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/resource.cc | 157 +++++++++++++++++++++++++--------------------- 1 file changed, 84 insertions(+), 73 deletions(-) diff --git a/winsup/cygwin/resource.cc b/winsup/cygwin/resource.cc index c4c79ca6f..21e85bd18 100644 --- a/winsup/cygwin/resource.cc +++ b/winsup/cygwin/resource.cc @@ -174,6 +174,87 @@ job_shared_name (PWCHAR buf, LONG num) return buf; } +static void +__get_rlimit_as (struct rlimit *rlp) +{ + 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) + && (jobinfo.BasicLimitInformation.LimitFlags + & JOB_OBJECT_LIMIT_PROCESS_MEMORY)) + rlp->rlim_cur = rlp->rlim_max = jobinfo.ProcessMemoryLimit; + if (job) + NtClose (job); +} + +static int +__set_rlimit_as (unsigned long new_as_limit) +{ + 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); + return -1; + } + jobinfo.BasicLimitInformation.LimitFlags + = JOB_OBJECT_LIMIT_PROCESS_MEMORY; + /* Per Linux man page, round down to system pagesize. */ + jobinfo.ProcessMemoryLimit + = rounddown (new_as_limit, wincap.allocation_granularity ()); + status = NtSetInformationJobObject (job, + JobObjectExtendedLimitInformation, + &jobinfo, sizeof jobinfo); + /* If creating the job and setting up the job limits succeeded, + try to add the process to the job. This must be the last step, + otherwise we couldn't remove the job if anything failed. */ + if (NT_SUCCESS (status)) + status = NtAssignProcessToJobObject (job, NtCurrentProcess ()); + NtClose (job); + if (!NT_SUCCESS (status)) + { + __seterrno_from_nt_status (status); + return -1; + } + cygheap->rlim_as_id = new_as_id; + return 0; +} + extern "C" int getrlimit (int resource, struct rlimit *rlp) { @@ -189,34 +270,7 @@ getrlimit (int resource, struct rlimit *rlp) 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); - } + __get_rlimit_as (rlp); break; case RLIMIT_STACK: __get_rlimit_stack (rlp); @@ -270,51 +324,8 @@ 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; - } + if (rlp->rlim_cur != RLIM_INFINITY) + return __set_rlimit_as (rlp->rlim_cur); break; case RLIMIT_CORE: cygheap->rlim_core = rlp->rlim_cur;