Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting EPERM when calling pthread_create() for SCHED_FIFO thread as root on Linux

Tags:

c

pthreads

I am trying to spawn threads with SCHED_FIFO or SCHED_RR policies as root on a Linux system but my calls to pthread_create() are returning 1 (EPERM). The man page for pthread_create() says that EPERM indicates that "[t]he caller does not have appropriate permission to set the required scheduling parameters or scheduling policy." Shouldn't root be able to specify SCHED_FIFO or SCHED_RR?

I've stripped out the code that creates a thread into a small program that does only that. It looks right to me but still gets the error. What am I doing wrong?

The program:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

static void *_Thread(void *arg)
{
    (void)arg;
    printf("Thread running!\n");
    return NULL;
}

int main(void)
{
    int retVal;
    pthread_attr_t attr;
    struct sched_param schedParam;
    pthread_t thread;

    retVal = pthread_attr_init(&attr);
    if (retVal)
    {
        fprintf(stderr, "pthread_attr_init error %d\n", retVal);
        exit(1);
    }

    retVal = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
    if (retVal)
    {
        fprintf(stderr, "pthread_attr_setinheritsched error %d\n", retVal);
        exit(1);
    }

    retVal = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
    if (retVal)
    {
        fprintf(stderr, "pthread_attr_setschedpolicy error %d\n", retVal);
        exit(1);
    }

    schedParam.sched_priority = 1;
    retVal = pthread_attr_setschedparam(&attr, &schedParam);
    if (retVal)
    {
        fprintf(stderr, "pthread_attr_setschedparam error %d\n", retVal);
        exit(1);
    }

    retVal = pthread_create(&thread,
                            &attr,
                            _Thread,
                            NULL);
    if (retVal)
    {
        fprintf(stderr, "pthread_create error %d\n", retVal);
        exit(1);
    }

    retVal = pthread_join(thread, NULL);
    if (retVal)
    {
        fprintf(stderr, "pthread_join error %d\n", retVal);
        exit(1);
    }

    printf("main run successfully\n");
    return 0;
}

This program has been compiled and run as root. When run, it program fails at the call to pthread_create, returning EPERM.

Changing the thread to SCHED_RR scheduling has no effect - EPERM still returned by pthread_create.

Changing the thread to SCHED_OTHER scheduling and its priority to 0 allows the program to run without error.

like image 569
ChrisL Avatar asked Feb 16 '12 14:02

ChrisL


People also ask

What does pthread_create() do with Eperm?

The man page for pthread_create () says that EPERM indicates that " [t]he caller does not have appropriate permission to set the required scheduling parameters or scheduling policy." Shouldn't root be able to specify SCHED_FIFO or SCHED_RR? I've stripped out the code that creates a thread into a small program that does only that.

What is the pthread_setschedparam () function?

The pthread_setschedparam () function sets the scheduling policy and parameters of the thread thread . policy specifies the new scheduling policy for thread. The supported values for policy, and their semantics, are described in sched (7) .

What is threading in Linux kernel?

In Linux threads run concurrently and are scheduled by the kernel asynchronously and hence the kernel interrupts a threads to allow another to execute from time to time. When a program is invoked, a new process is created and the process will have a single thread.

What is the enotsup error for pthread_setschedparam?

POSIX.1 also documents an ENOTSUP ("attempt was made to set the policy or scheduling parameters to an unsupported value") error for pthread_setschedparam (). POSIX.1-2001, POSIX.1-2008.


2 Answers

Surprisingly, I ran into the same problem as the OP almost 10 years later: CentOS 7.6, spawning a realtime thread, root user, ulimit -r says "unlimited", yet the thread creation fails returning EPERM. It turned out the failure is caused by the following clause in Linux kernel:

kernel/sched/core.c

          if (user) {
  #ifdef CONFIG_RT_GROUP_SCHED
                  /*
                   * Do not allow realtime tasks into groups that have
no runtime
                   * assigned.
                   */
                  if (rt_bandwidth_enabled() && rt_policy(policy) &&
                                  task_group(p)->rt_bandwidth.rt_runtime == 0 &&
                                  !task_group_is_autogroup(task_group(p))) {
                              task_rq_unlock(rq, p, &flags);
                              return -EPERM;
                  }
  #endif

Given that, and Linux cgroup documentation https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt, and CONFIG_RT_GROUP_SCHED documentation https://www.kernel.org/doc/Documentation/scheduler/sched-rt-group.txt, the problem is resolved by adding the current shell to the existing cgroup with realtime scheduling info:

cd /sys/fs/cgroup/cpu
echo $$ > tasks

Then running the executable spawning a realtime thread from the current shell the thread creation succeeds.

like image 188
glagolig Avatar answered Oct 17 '22 04:10

glagolig


Run the program as root user. Because we are messing with scheduling (its for FIFO and RR). you're messing also (by implication) with relative priorities, and that only root can do.

Running above program normally, pthread_create() returns EPERM, but as root user is works fine.

For more info visit: http://www.linuxforums.org/forum/programming-scripting/111359-pthread-error.html

like image 23
Himanshu Sharma Avatar answered Oct 17 '22 02:10

Himanshu Sharma