prlimit(), prlimit64()

Updated: April 19, 2023

Set and get the limit on a system resource

Synopsis:

#include <sys/resource.h>

int prlimit( pid_t pid,
             int resource,
             const struct rlimit * new_rlp,
             struct rlimit * old_rlp );

int prlimit64( pid_t pid,
               int resource,
               const struct rlimit64 * new_rlp,
               struct rlimit64 * old_rlp );

Arguments:

pid
The ID of the process to set or get the limit for. If pid is 0, the call applies to the calling process.
resource
The resource whose limit you want to get or set. For a list of the possible resources, their descriptions, and the actions taken when the current limit is exceeded, see below.
new_rlp
If this argument is not NULL, the rlimit structure that it points to is used to set new values for the soft and hard limits for resource.
old_rlp
If this argument is not NULL, a successful call to prlimit() places the previous soft and hard limits for resource in the rlimit structure that old_rlp points to.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The prlimit() and prlimit64() functions can be used to set and get limits on the consumption of a variety of system resources by a process and each process it creates. They combine and extend the functionality of setrlimit() and getrlimit(). The prlimit64() function is a large-file support version of prlimit().

Note: In QNX Neutrino 6.6 or later, the large-file support functions and data types appear in the name space only if you define _LARGEFILE64_SOURCE when you compile your code. For more information, see Classification in What's in a Function Description?

The possible resources, their descriptions, and the actions taken when the current limit is exceeded are summarized below (the “_NP” in some names stands for “non-POSIX”):

Resource Classification Description Action
RLIMIT_AS POSIX The maximum size, in bytes, of a process's mapped address space. If the limit is exceeded, mmap() fails with errno set to ENOMEM. In addition, the automatic stack growth fails with the effects outlined above.
RLIMIT_CORE POSIX The maximum size, in bytes, of a core file that a process may create. A limit of 0 prevents the creation of a core file. The writing of a core file terminates at this size.
RLIMIT_CPU POSIX The maximum amount of CPU time, in seconds, that a process may use. This is a soft limit only. If the limit is exceeded, SIGXCPU is sent to the process. If the process is ignoring SIGXCPU, SIGKILL is sent to the process.
RLIMIT_DATA POSIX The maximum size, in bytes, that a process's heap may be. In QNX Neutrino, RLIMIT_DATA covers all mappings made by the process that are MAP_ANON | MAP_PRIVATE that aren't MAP_STACK, which corresponds typically to heap allocations. If the limit is exceeded, mmap() fails with errno set to ENOMEM.
RLIMIT_FREEMEM Unix The limit on total memory usage, in tenths of a per cent of the total system memory. For example, a limit of 500 on a system with 1000 MB of memory would be 500 MB. This limit is shared with all other processes; a memory allocation by this process fails if it would cause the total system memory usage of all processes to exceed this process's limit.

The intention is to allow the memory pool to be crudely partitioned. For example, important system processes could be given an RLIMIT_FREEMEM value of RLIM_INFINITY, and all others a value of 800. That would partition memory into an 80% chunk that's shared by everybody and a 20% chunk that's shared by important system processes.

RLIMIT_NOCONN_NP QNX Neutrino The maximum number of connections a process can create, including file descriptors and side-channel connections. Most processes are created with three fds (stdin, stdout, and stderr) and a connection to the system process.

RLIMIT_NOCONN_NP should be greater than or equal to RLIMIT_NOFILE; it's up to you to set these limits so that they don't conflict.

ConnectAttach() gives an error of EMFILE
RLIMIT_NOFILE POSIX One more than the maximum value that the system may assign to a newly created descriptor. This limit constrains the number of file descriptors that a process may create. Functions that allocate a file descriptor give an error of EMFILE
RLIMIT_NPROC Unix The maximum number of processes. Attempts to create new processes fail.
RLIMIT_NTHR Unix The maximum number of threads. Attempts to create threads (e.g., by calling pthread_create()) fail.
RLIMIT_OFILE Unix Same as RLIMIT_NOFILE.  
RLIMIT_RSS Unix The maximum resident set size for a process; the same as RLIMIT_AS. Same as RLIMIT_AS.
RLIMIT_SIGEVENT_NP QNX Neutrino The maximum number of sigevents that a process can have registered at a given time. MsgRegisterEvent() gives an error of EAGAIN.
RLIMIT_STACK POSIX The maximum size, in bytes, that a process's stack may be. The system will not automatically grow the stack beyond this limit.

Within a process, prlimit() increases the limit on the size of your stack, but doesn't move current memory segments to allow for that growth. To guarantee that the process stack can grow to the limit, the limit must be altered prior to the execution of the process in which the new stack size is to be used.

Within a multithreaded process, prlimit() has no impact on the stack size limit for the calling thread if the calling thread isn't the main thread. A call to prlimit() for RLIMIT_STACK impacts only the main thread's stack, and should be made only from the main thread, if at all.

The SIGSEGV signal is sent to the process. If the process is holding or ignoring SIGSEGV, or is catching SIGSEGV and hasn't made arrangements to use an alternate stack, the disposition of SIGSEGV is set to SIG_DFL before it's sent.
RLIMIT_TIMERS_NP QNX Neutrino The maximum number of timers that a process can create. Attempts to create timers by calling timer_create() or TimerCreate() fail with an error of EAGAIN. Note that this limit doesn't apply to TimerTimeout()
RLIMIT_VMEM Unix Same as RLIMIT_AS. Same as RLIMIT_AS.

Because limit information is stored in the per-process information, the shell builtin ulimit command (see the entry for ksh in the Utilities Reference) must directly execute this system call if it's to affect all future processes created by the shell.

The values of the current limit of the following resources affect these parameters:

Resource Parameter
RLIMIT_NOFILE OPEN_MAX
When you get a resource limit:
  • If the resource limit can be represented correctly in an object of type rlim_t, then its representation is returned.
  • If the value of the resource limit is equal to that of the corresponding saved hard limit, the value returned is RLIM_SAVED_MAX.
  • For all other resource limit values, the value returned is RLIM_SAVED_CUR.
When you set a resource limit:
  • If the new limit requested is RLIM_INFINITY, the new limit is "no limit".
  • If the requested new limit is RLIM_SAVED_MAX the limit is set to the corresponding saved hard limit.
  • If the requested new limit is RLIM_SAVED_CUR, the limit is set to the corresponding saved soft limit.
  • For all other resource limit values, the limit is set to the requested value.

The result of setting a limit to RLIM_SAVED_MAX or RLIM_SAVED_CUR is unspecified unless a previous call to prlimit() returned that value as the soft or hard limit for the corresponding resource limit.

A limit whose value is greater than RLIM_INFINITY is permitted.

Returns:

0
Success.
-1
An error occurred (errno is set).

Errors:

EFAULT
Either new_rlp or old_rlp points to an illegal address.
EINVAL
An invalid resource or an invalid value for the resource was specified.
EPERM
The calling process does not have the required permissions to set resource limits on the process with PID pid. (See procmgr_ability().)
ESRCH
The process specified by pid does not exist.

Examples:

struct rlimit old;
struct rlimit new;
pid_t pid;
int ret;

pid = ...

// Get the old limit for RLIMIT_CPU
ret = prlimit(pid, RLIMIT_CPU, NULL, &old);
if (ret != 0) {
    perror("prlimit");
    return errno;
}
printf("old: cur=%lu, max=%lu \n", old.rlim_cur, old.rlim_max);

new.rlim_cur = ...
new.rlim_max = ...
printf("new: cur=%lu, max=%lu \n", new.rlim_cur, new.rlim_max);

// Get and set the limit for RLIMIT_CPU
ret = prlimit(pid, RLIMIT_CPU, &new, &old);
if (ret != 0) {
    perror("prlimit");
    return errno;
}
printf("old: cur=%lu, max=%lu \n", old.rlim_cur, old.rlim_max);

Classification:

prlimit64() is Large-file support

Safety:  
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes