Skip to content

Commit

Permalink
Add RLIMIT_NOFILE support to omrsysinfo_set_limit
Browse files Browse the repository at this point in the history
Also update tests.

Fixes eclipse-omr#3501

Signed-off-by: Peter Bain <[email protected]>
  • Loading branch information
pdbain-ibm committed Jan 28, 2019
1 parent b8a14eb commit 0549539
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 46 deletions.
139 changes: 138 additions & 1 deletion fvtest/porttest/si.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1991, 2018 IBM Corp. and others
* Copyright (c) 1991, 2019 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -796,6 +796,143 @@ TEST(PortSysinfoTest, sysinfo_test_sysinfo_set_limit_CORE_FILE)
reportTestExit(OMRPORTLIB, testName);
}

/**
*
* Test omrsysinfo_test_sysinfo_set_limit and omrsysinfo_test_sysinfo_get_limit
* with resourceID OMRPORT_RESOURCE_FILE_DESCRIPTORS
*
*/
TEST(PortSysinfoTest, sysinfo_test_sysinfo_set_limit_FILE_DESCRIPTORS)
{
OMRPORT_ACCESS_FROM_OMRPORT(portTestEnv->getPortLibrary());
const char *testName = "omrsysinfo_test_sysinfo_set_limit_FILE_DESCRIPTORS";
intptr_t rc = -1;
uint64_t originalSoftLimit = 0;
uint64_t finalSoftLimit = 0;
uint64_t originalHardLimit = 0;
uint64_t currentLimit = 0;
const uint64_t descriptorLimit = 256;

reportTestEntry(OMRPORTLIB, testName);

/* save original soft limit */
rc = omrsysinfo_get_limit(OMRPORT_RESOURCE_FILE_DESCRIPTORS, &originalSoftLimit);
if (OMRPORT_LIMIT_UNKNOWN == rc) {
outputErrorMessage(PORTTEST_ERROR_ARGS, "omrsysinfo_get_limit FAILED: OMRPORT_LIMIT_UNKNOWN\n");
reportTestExit(OMRPORTLIB, testName);
return;
}
finalSoftLimit = originalSoftLimit;

rc = omrsysinfo_set_limit(OMRPORT_RESOURCE_FILE_DESCRIPTORS, descriptorLimit);
if (0 != rc) {
outputErrorMessage(PORTTEST_ERROR_ARGS, "omrsysinfo_set_limit FAILED rc=%d\n", rc);
reportTestExit(OMRPORTLIB, testName);
return;
}

rc = omrsysinfo_get_limit(OMRPORT_RESOURCE_FILE_DESCRIPTORS, &currentLimit);
if (OMRPORT_LIMIT_UNKNOWN == rc) {
outputErrorMessage(PORTTEST_ERROR_ARGS, "omrsysinfo_get_limit FAILED: OMRPORT_LIMIT_UNKNOWN\n");
reportTestExit(OMRPORTLIB, testName);
return;
}
if (descriptorLimit == currentLimit) {
portTestEnv->log("omrsysinfo_set_limit set FILE_DESCRIPTORS soft limit successful\n");
} else {
outputErrorMessage(PORTTEST_ERROR_ARGS,
"omrsysinfo_set_limit set FILE_DESCRIPTORS soft limit FAILED originalSoftLimit=%lld Expected=%lld actual==%lld\n",
originalSoftLimit, descriptorLimit, currentLimit);
reportTestExit(OMRPORTLIB, testName);
return;
}

/* save original hard limit */
rc = omrsysinfo_get_limit(OMRPORT_RESOURCE_FILE_DESCRIPTORS | OMRPORT_LIMIT_HARD, &originalHardLimit);
if (OMRPORT_LIMIT_UNKNOWN == rc) {
outputErrorMessage(PORTTEST_ERROR_ARGS, "omrsysinfo_get_limit FAILED: OMRPORT_LIMIT_UNKNOWN\n");
reportTestExit(OMRPORTLIB, testName);
return;
}

/* lowering the hard limit is irreversible unless privileged */
if (0 != geteuid()) { /* normal user */
/* setting the hard limit from unlimited to a finite value has unpredictable results:
* the actual value may be much smaller than requested.
* In that case, just try setting it to the same value.
*/
uint64_t newHardLimit = (OMRPORT_LIMIT_UNLIMITED == rc) ? originalHardLimit: originalHardLimit - 1;

rc = omrsysinfo_set_limit(OMRPORT_RESOURCE_FILE_DESCRIPTORS | OMRPORT_LIMIT_HARD, newHardLimit);
if (0 != rc) {
outputErrorMessage(PORTTEST_ERROR_ARGS, "omrsysinfo_set_limit set hard limit FAILED rc=%d\n", rc);
reportTestExit(OMRPORTLIB, testName);
return;
}

rc = omrsysinfo_get_limit(OMRPORT_RESOURCE_FILE_DESCRIPTORS | OMRPORT_LIMIT_HARD, &currentLimit);
if (OMRPORT_LIMIT_UNKNOWN == rc) {
outputErrorMessage(PORTTEST_ERROR_ARGS, "omrsysinfo_get_limit FAILED: OMRPORT_LIMIT_UNKNOWN\n");
reportTestExit(OMRPORTLIB, testName);
return;
}
if (newHardLimit == currentLimit) {
portTestEnv->log("omrsysinfo_set_limit set FILE_DESCRIPTORS hard limit successful\n");
} else {
outputErrorMessage(PORTTEST_ERROR_ARGS,
"omrsysinfo_set_limit set FILE_DESCRIPTORS hard limit FAILED originalHardLimit=%lld Expected=%lld actual==%lld\n",
originalHardLimit, newHardLimit, currentLimit);
reportTestExit(OMRPORTLIB, testName);
return;
}
finalSoftLimit = (originalSoftLimit > newHardLimit)? newHardLimit: originalSoftLimit;
} else { /* running as root */
const uint64_t newHardLimit = 257;
rc = omrsysinfo_set_limit(OMRPORT_RESOURCE_FILE_DESCRIPTORS | OMRPORT_LIMIT_HARD, newHardLimit);
if (0 != rc) {
outputErrorMessage(PORTTEST_ERROR_ARGS, "omrsysinfo_set_limit FAILED rc=%d\n", rc);
reportTestExit(OMRPORTLIB, testName);
return;
}

rc = omrsysinfo_get_limit(OMRPORT_RESOURCE_FILE_DESCRIPTORS | OMRPORT_LIMIT_HARD, &currentLimit);
if (OMRPORT_LIMIT_UNKNOWN == rc) {
outputErrorMessage(PORTTEST_ERROR_ARGS, "omrsysinfo_get_limit FAILED: OMRPORT_LIMIT_UNKNOWN\n");
reportTestExit(OMRPORTLIB, testName);
return;
}
if (newHardLimit == currentLimit) {
portTestEnv->log("omrsysinfo_set_limit set FILE_DESCRIPTORS hard limit successful\n");
} else {
outputErrorMessage(PORTTEST_ERROR_ARGS,
"omrsysinfo_set_limit set FILE_DESCRIPTORS hard max FAILED. Expected=%lld actual=%lld\n",
(descriptorLimit + 1), currentLimit);
reportTestExit(OMRPORTLIB, testName);
return;
}

/* restore original hard limit */
rc = omrsysinfo_set_limit(OMRPORT_RESOURCE_FILE_DESCRIPTORS | OMRPORT_LIMIT_HARD, originalHardLimit);
if (0 != rc) {
outputErrorMessage(PORTTEST_ERROR_ARGS, "restoring the original hard limit FAILED rc=%d\n", rc);
reportTestExit(OMRPORTLIB, testName);
return;
}
}

/* restore original soft limit
The soft limit is always <= the hard limit. If the hard limit is lowered to below the soft limit and
then raised again the soft limit isn't automatically raised. */
rc = omrsysinfo_set_limit(OMRPORT_RESOURCE_FILE_DESCRIPTORS, finalSoftLimit);
if (0 != rc) {
outputErrorMessage(PORTTEST_ERROR_ARGS, "restoring the original soft limit FAILED rc=%d\n", rc);
reportTestExit(OMRPORTLIB, testName);
return;
}

reportTestExit(OMRPORTLIB, testName);
}

#if defined(AIXPPC)
/**
*
Expand Down
4 changes: 3 additions & 1 deletion port/common/omrsysinfo.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1991, 2018 IBM Corp. and others
* Copyright (c) 1991, 2019 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -469,6 +469,8 @@ omrsysinfo_get_limit(struct OMRPortLibrary *portLibrary, uint32_t resourceID, ui
* Operating system specific core information
* On AIX this attempts to set the sys_parm fullcore value to limit (requires root to successfully change)
* No effect on other operating systems
* OMRPORT_RESOURCE_FILE_DESCRIPTORS
* Sets the maximum number of file descriptors that can opened in a process.
*
* resourceID may be bit-wise or'ed with one of:
* OMRPORT_LIMIT_SOFT
Expand Down
96 changes: 52 additions & 44 deletions port/unix/omrsysinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -2359,74 +2359,82 @@ omrsysinfo_set_limit(struct OMRPortLibrary *portLibrary, uint32_t resourceID, ui

Trc_PRT_sysinfo_set_limit_Entered(resourceID, limit);

if (OMRPORT_RESOURCE_ADDRESS_SPACE == resourceRequested) {
switch (resourceRequested) {
case OMRPORT_RESOURCE_FILE_DESCRIPTORS:
resource = RLIMIT_NOFILE;
break;
case OMRPORT_RESOURCE_ADDRESS_SPACE:
#if !defined(OMRZTPF)
resource = RLIMIT_AS;
#else /* !defined(OMRZTPF) */
/* z/TPF does not have virtual address support */
rc = -1;
Trc_PRT_sysinfo_set_limit_Exit(rc);
return rc;
#endif /* !defined(OMRZTPF) */
} else if (OMRPORT_RESOURCE_CORE_FILE == resourceRequested) {
break;
case OMRPORT_RESOURCE_CORE_FILE:
#if !defined(OMRZTPF)
resource = RLIMIT_CORE;
#else /* !defined(OMRZTPF) */
rc = -1;
Trc_PRT_sysinfo_set_limit_Exit(rc);
return rc;
#endif /* !defined(OMRZTPF) */
break;
default:
break;
}

switch (resourceRequested) {
case OMRPORT_RESOURCE_ADDRESS_SPACE:
/* FALLTHROUGH */
case OMRPORT_RESOURCE_CORE_FILE: {
if (0 == rc) {
switch (resourceRequested) {
case OMRPORT_RESOURCE_FILE_DESCRIPTORS:
/* FALLTHROUGH */
case OMRPORT_RESOURCE_ADDRESS_SPACE:
/* FALLTHROUGH */
case OMRPORT_RESOURCE_CORE_FILE: {
#if !defined(OMRZTPF)
rc = getrlimit(resource, &lim);
if (-1 == rc) {
portLibrary->error_set_last_error(portLibrary, errno, findError(errno));
Trc_PRT_sysinfo_getrlimit_error(resource, findError(errno));
break;
}
rc = getrlimit(resource, &lim);
if (-1 == rc) {
portLibrary->error_set_last_error(portLibrary, errno, findError(errno));
Trc_PRT_sysinfo_getrlimit_error(resource, findError(errno));
break;
}

if (hardLimitRequested) {
lim.rlim_max = limit;
} else {
lim.rlim_cur = limit;
}
if (hardLimitRequested) {
lim.rlim_max = limit;
} else {
lim.rlim_cur = limit;
}

rc = setrlimit(resource, &lim);
if (-1 == rc) {
portLibrary->error_set_last_error(portLibrary, errno, findError(errno));
Trc_PRT_sysinfo_setrlimit_error(resource, limit, findError(errno));
}
rc = setrlimit(resource, &lim);
if (-1 == rc) {
portLibrary->error_set_last_error(portLibrary, errno, findError(errno));
Trc_PRT_sysinfo_setrlimit_error(resource, limit, findError(errno));
}
#else /* !defined(OMRZTPF) */
rc = -1;
rc = -1;
#endif /* !defined(OMRZTPF) */
break;
}
break;
}

case OMRPORT_RESOURCE_CORE_FLAGS: {
case OMRPORT_RESOURCE_CORE_FLAGS: {
#if defined(AIXPPC)
struct vario myvar;
struct vario myvar;

myvar.v.v_fullcore.value = limit;
rc = sys_parm(SYSP_SET, SYSP_V_FULLCORE, &myvar);
if (-1 == rc) {
portLibrary->error_set_last_error(portLibrary, errno, findError(errno));
Trc_PRT_sysinfo_sysparm_error(errno);
}
myvar.v.v_fullcore.value = limit;
rc = sys_parm(SYSP_SET, SYSP_V_FULLCORE, &myvar);
if (-1 == rc) {
portLibrary->error_set_last_error(portLibrary, errno, findError(errno));
Trc_PRT_sysinfo_sysparm_error(errno);
}
#else
/* unsupported so return error */
rc = -1;
/* unsupported so return error */
rc = -1;
#endif
break;
}
break;
}

default:
Trc_PRT_sysinfo_setLimit_unrecognised_resourceID(resourceID);
rc = -1;
default:
Trc_PRT_sysinfo_setLimit_unrecognised_resourceID(resourceID);
rc = -1;
}
}

Trc_PRT_sysinfo_set_limit_Exit(rc);
Expand Down

0 comments on commit 0549539

Please sign in to comment.