aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2021-11-30 12:54:03 +0100
committerCorinna Vinschen <corinna@vinschen.de>2021-11-30 12:55:14 +0100
commit3edea7cd55d178164a649d9eea252c807ed2c038 (patch)
tree6225e46f8ea9b61950545c613e07c1983146631a /winsup
parent670beaed0216aa59603501e8f14e1f04b138bc47 (diff)
downloadnewlib-3edea7cd55d178164a649d9eea252c807ed2c038.zip
newlib-3edea7cd55d178164a649d9eea252c807ed2c038.tar.gz
newlib-3edea7cd55d178164a649d9eea252c807ed2c038.tar.bz2
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 <corinna@vinschen.de>
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/resource.cc157
1 files changed, 84 insertions, 73 deletions
diff --git a/winsup/cygwin/resource.cc b/winsup/cygwin/resource.cc
index c4c79ca..21e85bd 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;