0

This is likely a setting related matter.

Problem: Unable to generate more than 70 pthreads on our public Redhat environments. Expectation is several thousand.

The attached program is designed to demonstrate to students the use of mutex semaphores for controlling access to shared data while also showing the ability of a system to handle many more pthreads than processes. It’s part of a teaching unit on creating a network server program.

Unfortunately the program fails at about 70 pthreads, which indicates the same limit as the number of concurrent processes allowed on our systems, which is set to a default of 75. This happens on both our two Enterprise student environments – one is Redhat 5.11 and the other is Redhat 6.8 . These are our shared environments which we use to give demos and students do assignments.

On a downloaded version of Redhat 7 as well as on Ubuntu 15.04, both running under VMWare I'm able to generate several thousand threads, which is what I'd expect.

The problem, when it occurs, becomes evident in the initial for loop in main.

/*
File: pthreadDemo2.c
Course: CENG320
Author: Prof. Leon King,J230,x4200
Date: Friday Jun 16, 2017   14:26 PM

In this demo we list the status of threads and selectively cancel them.
The commands are:  list  (list)
kill  #  kill a thread by number
inc      have threads increment the counter
INC   #  increment a specific counter  
quit     end the program
show     show the counter

Compile with the thread library -pthread
See also:  http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
 */


#include <pthread.h>
#include <bits/local_lim.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
/* We have no predefined limit on the number of threads.  */
#define NUMBER_OF_THREADS 4000 

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; //Warning! This is a shared global variable!
long counter=0;

void incrementCounter(int signum)
{
    //pthread_mutex_lock(&mutex); 
    int c2;
    c2=counter;
    c2=c2+1;
    counter=c2;
    //fprintf(stdout,"Changing a counter\n"); 
    /*FILE *log=fopen("threadSafeLog.dat","a");
      fprintf(log,"Logging event for thread %u\n",(int) pthread_self()); 
      fprintf(log,"Logging event 2nd write for thread %u\n",(int) pthread_self()); 
      fclose(log);
     */
    //pthread_mutex_unlock(&mutex);
}

void *threadProcedure(void * arg)
{
    int myThreadInfo=(long) arg,
    threadID=pthread_self();
    while(1) pause();  
    pthread_exit(0);  //calling exit() would end all threads & main

}

int main(int argc, char * argv[],char * envp[])
{
    pthread_t threadList[NUMBER_OF_THREADS]={0};
    char cmd[20];

    pthread_mutex_init(&mutex,NULL); 
    pthread_attr_t threadAttributes; 
    pthread_attr_init(&threadAttributes);

    int err1=pthread_attr_setstacksize(&threadAttributes, 16384);
    if(err1) fprintf(stdout,"Error in setting the stack size: %d\n", err1);

    signal(SIGUSR1,incrementCounter);  
    fprintf(stdout,"Hello World. I'm %d\n",(int) getpid()); 
    //
    //Spawn a group of threads
    //THIS IS THE CORE OF THE PROBLEM
    //IT CAN GENERATE OVER 6K threads on a Ubuntu 15.04 Release
    //BUT only 70 threads on Redhat 5.11 and 6.8 Enterprise
    //The focus question is: How does one increase the limit on the number of threads in Redhat 
    for(int i=0;i<NUMBER_OF_THREADS;i++) 
    {
    if(!pthread_create(&threadList[i],&threadAttributes,threadProcedure,(void *)i))
        {
            pthread_detach(threadList[i]); 
         }
     else   perror("Failure to create a thread");

    }

    while(1)
    {
        fprintf(stdout,"Commands: list, show, increment, quit\n");
    fscanf(stdin,"%s",cmd);
    switch(cmd[0])
    {

        case 'l': for(int i=0;i<NUMBER_OF_THREADS;i++)
              fprintf(stdout,"thread id of threadlist[%d]: %u\n",i,(int) threadList[i]); 
              break;

        case 's':  fprintf(stdout,"Counter value: %lu\n",counter);
               break;

               break;

        case 'i': fprintf(stdout,"Initial value of counter: %lu\n",counter);     
              for(int i=0;i<100;i++)
              {
                  int error= pthread_kill(threadList[i],SIGUSR1);
                  if(error) {perror("Failed signal"); errno=0;}

              }
              fprintf(stdout,"Final value of Counter? %lu\n",counter);  
              break;

        case 'q':  exit(0); 

    }

    }

    return 0;

}
  • You can increase the number with this `echo new_size > /proc/sys/kernel/threads-max` – Seek Addo Aug 08 '17 at 20:28
  • You need to run the program under `strace` (or a debugger) to see *why* the thread creation is failing. With the configured thread size, the limit is suspiciously low. – Florian Weimer Aug 08 '17 at 20:36
  • _"while also showing the ability of a system to handle many more pthreads than processes."_. This is not quite correct. linux threads [and pthreads on most modern systems] are synonymous with processes (i.e. there is a one-to-one mapping, and not a one-to-many mapping). To prevent denial-of-service, your servers have the 75 cap set. For more info, see my answer: https://stackoverflow.com/questions/39185134/how-are-user-level-threads-scheduled-created-and-how-are-kernel-level-threads-c/39185831#39185831 – Craig Estey Aug 08 '17 at 21:21
  • threads-max is currently set to 970007 so that's not the problem. – user3066489 Aug 11 '17 at 01:48
  • The fact that I can get several thousand processes running under VMWare and other versions of Linus indicates that processes and threads are not synonymous. strace may be a good lead. Under Redhat 5.11 the pthread_create generates calls to clone. I need to compare this to the behaviour on other system. – user3066489 Aug 11 '17 at 02:03
  • I took another look at my VMWare setups. The process limit was much higher and when I reduced it I had a similar problem. So the previous comments appear to be correct - the # of threads is tied to the # of processes. – user3066489 Aug 11 '17 at 14:51

1 Answers1

1

Yes, under linux, threads and processes are handled very similarly.

If you have set a process limit of 75, that's really a limit on total number of threads for all processes of a user. So this works as it is designed.

A limit of the number of processes is set with the ulimit command or in /etc/limits.conf which is applied with the setrlimit() system call, From its documentation

RLIMIT_NPROC This is the maximum number of processes (or, more precisely on Linux, threads) that can be created for the real user ID of the calling process.

nos
  • 223,662
  • 58
  • 417
  • 506
  • 1
    `ulimit` is the Bash/POSIX shell built-in command, but there's also the external command [`prlimit`](http://man7.org/linux/man-pages/man1/prlimit.1.html), if one uses a non-Bash, non-POSIX shell. – Nominal Animal Aug 08 '17 at 21:05