https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=3edea7cd55d178164a649d9eea252c807ed2c038

commit 3edea7cd55d178164a649d9eea252c807ed2c038
Author: Corinna Vinschen <[email protected]>
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 <[email protected]>

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;

Reply via email to