Bus error on OSX - pthreads - c

am trying to get my head around the following:
Have a small program am trying to port to OSX(intel) which calls function doWork()
via pthread_create, in the function, I start by creating an array of long like such:
long myarray[DIMENSION]
on OSX, for the following values of DIMENSION, I get the following:
0->65434 = fine
65435->67037 = SIGBUS
67037+ = SIGSEGV
I'm totally confused here, I understand that SIGBUS is due to memory alignment issues usually, I checked sizeof(long) and it appears to be 8 on this platform. Can somebody point me in the right direction of docs I should be reading here?
Here is the source:
#include pthread.h
#include stdio.h
#define NUM_THREADS 5
#define DIMENSION 12345
void *doStuff(void *threadid)
{
long array[DIMENSION];
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t lt NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, doStuff, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}

It would appear you're overflowing the stack.
You'll need to either turn the long array into a malloced one, or use pthread_attr_setstacksize and friends to create a larger stack when you call pthread_create.
Default thread stack sizes vary a lot between platforms, which would explain why the code works on other platforms.
Example code:
pthread_attr_t attr;
size_t stacksize;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &stacksize);
printf("Default stack size = %li\n", stacksize);
stacksize = <....>;
printf("Amount of stack needed per thread = %li\n",stacksize);
pthread_attr_setstacksize(&attr, stacksize);
rc = pthread_create(&thread, &attr, dowork, (void *)t);
(code originally from https://github.com/LLNL/HPC-Tutorials/blob/main/posix/stack_management.md )
As to why you get a sigbus, it's probably because the act of creating the array is overwriting some part of pthreads internal data structures with garbage, resulting in an alignment error when pthreads tries to clean up the thread.

Related

Thread C segmentation fault a simple program

I need your help to find the problem in this code: it's the main function of my program that simulates a multiprocessor system. I use thread library to build the Ram entity and all CPUs. Compiling there aren't problems and most of the executions work well. But, sometime, I launch the exe and after one or two prints, there is a segmentation fault.
So, I try to find it using gdb (without any response) and valgrind. The only thing that Valgrind told to me is that there was only a possibly lost (this is the messagge: 272 bytes in 1 blocks are possibly lost in loss record 1 of 1).
Ps. I write #include for each library function.
int main(int argc, char *argv[])
{
if(argc!=3)
syserr("Utilizzo: simulazione <numCpu> <ramDim>\n");
pthread_t ram;
ram_dim=atoi(argv[2]);
int num_cpu=atoi(argv[1]);
pthread_t cpu[num_cpu];
command *cpu_info=(command *) malloc(sizeof(command)*num_cpu);
request *buffer=(request *) malloc(sizeof(request));
int curs, status;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_mutex_init(&ram_lock, NULL);
vpthread_mutex_lock(&ram_lock);
if((status=pthread_create(&ram, &attr, ram_job, (void *) buffer))!=0)
syserr("Creazione thread Ram fallita.\n");
pthread_mutex_init(&cpu_lock, NULL);
pthread_mutex_init(&rw_lock, NULL);
pthread_mutex_lock(&rw_lock);
for(curs=0;curs<num_cpu;curs++)
{
cpu_info[curs].istr=buffer;
cpu_info[curs].num_cpu=curs+1;
if((status=pthread_create(&cpu[curs], &attr, cpu_job, (void *) &cpu_info[curs]))!=0)
syserr("Creazione thread Cpu fallita.\n");
}
pthread_attr_destroy(&attr);
for(curs=0;curs<num_cpu;curs++)
pthread_join(cpu[curs], (void **) 0);
free(buffer);
free(cpu_info);
pthread_mutex_destroy(&rw_lock);
pthread_mutex_destroy(&cpu_lock);
pthread_mutex_destroy(&ram_lock);
return 0;
}
Because if there's an error, syserr will return. If there's an error, it will do something close to "printf(...); exit(...);".
And you will never do the rest of the code, which is suppose to free all variables.
Use "strerror(errno)" instead ;)
Join with that thread is missing. Add:
pthread_join(ram, 0);
Somewhere at the end before you destroy the resources used by that thread.
But that probably won't fix that crash because you need first to stop that thread gracefully somehow.

Main() thread id is different after creating another thread

I've been reading and learning about POSIX threads, and tried to write some simple codes to understand it better.
#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */
/* function to be executed by the new thread */
void* PrintHello(void* data)
{
pthread_t tid = (pthread_t)data;
printf("Hello from new thread %d - got %d\n", pthread_self(), tid);
pthread_exit(NULL); /* terminate the thread */
}
int main(int argc, char* argv[])
{
int rc; /* return value */
pthread_t thread_id;
int tid;
thread_id = pthread_self();
printf("FLAG = %d ", thread_id);
/* create a new thread that will execute 'PrintHello' */
rc = pthread_create(&thread_id, NULL, PrintHello, (void*)thread_id);
if(rc) /* could not create thread */
{
printf("\n ERROR: return code from pthread_create is %u \n", rc);
exit(1);
}
printf("\n Created new thread (%d) ... \n", thread_id);
pthread_exit(NULL); /* terminate the thread */
}
For this code I get the following output:
FLAG = 363480832
Created new thread (355198720) ...
Hello from new thread 355198720 - got 363480832
What is bothering me is why thread_id which is 363480832, becomes 355198720, same as thread_id of a function that was called from main (PrintHello()). I assumed that thread id doesn't change throughout the program execution. Or is it something inside the function that changes it?
If you're doing anything with a pthread_t other than passing it to a function that takes one, you're doing something wrong. Only the pthreads API knows how to use a pthread_t correctly. They can have any internal structure that's convenient for the implementation.
Being a C language construct, pthread_t behaves more like char *. The necessary language constructs to make it behave like std::string don't exist. So you have to treat it like char *.
A char * contains a string somehow, but you have to understand its implementation to get that value out. Consider:
char *j = "hello";
char *k = strdup (j);
if (j == k)
printf ("This won't happen\n");
printf ("%d\n", j);
printf ("%d\n", k); // these won't be equal
You can't compare char *'s with == to see if they refer to the same string. And if you print out j and k, you'll get different values.
Similarly, a pthread_t refers to one particular thread somehow. But you have to understand how to get the value out. Two pthread_ts can have different apparent values but still refer to the same thread just as two char *s can have different apparent values but still refer to the same string.
Just as you compare two char *'s with strcmp if you want to tell if they refer to the same string value, you compare two pthread_ts with pthread_equal to tell if they refer to the same thread.
So this line of code makes no sense:
printf("FLAG = %d ", thread_id);
A pthread_t is not an integer and you can't print it with a %d format specifier. POSIX has no printable thread IDs. If you want one, you need to code one (perhaps using pthread_getspecific).
In C, arguments are passed by value. In particular, the argument (void *)thread_id is an expression that's evaluated before calling pthread_create, so the fact that pthread_create writes to thread_id as a result of &thread_id being passed as the first argument is irrelevant. If you were instead passing &thread_id rather than (void *)thread_id as the argument to the new thread start function, and dereferencing it there, then you may see the effects you want; however, it's not clear to me that pthread_create's writing of the new thread id via its first argument is required to take place before the new thread starts, so there is probably a data race if you do it that way.
Further, note that David's answer is also correct. It's invalid to print thread ids this way since they are formally an opaque type.
In this line:
rc = pthread_create(&thread_id, NULL, PrintHello, (void*)thread_id);
as the manual says, pthread_create() shall store the ID of the created thread in the location referenced by thread_id. In this example, it would be modified to 355198720, which is the tid of new thread PrintHello().
Besides, it may be better to change the argument for PrintHello to:
rc = pthread_create(&thread_id, NULL, PrintHello, (void*)&thread_id);
and in PrintHello(), it would be:
void* PrintHello(void* data)
{
pthread_t tid = (pthread_t)(*data);
...
}

POSIX parent/child threads not sharing data

One final question for the evening. I have a homework question that I cannot seem to solve, and after spending the better part of the night on it, I'll ask it here.
The problem is a program that is to calculate the Fibonacci sequence given an integer input at the command line (./foo.out 15, for example, and it will calculate the first 15 Fibonacci numbers). The additional parameters are as follows:
1.) It must use two POSIX threads, a parent thread and a child thread.
2.) It must share data (an array) between them.
Currently, the function is breaking when program control passes back to the parent thread. All I am getting is a completely non-descriptive segfault. As can be seen below, I have it outputting at every possible change in control.
Code:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
void *fibonacci(void *param, int numbers[]);
void *runner(void *param);
int main(int argc, char *argv[])
{
pthread_t tid;
pthread_attr_t attr;
if ( argc != 2)
{
fprintf(stderr, "Usage: 426.out <integer value> \n");
return -1;
}
if (atoi(argv[1]) < 0)
{
fprintf(stderr, "Argument must be non-negative\n");
return -2;
}
pthread_attr_init(&attr);
pthread_create(&tid, &attr, runner, argv[1]);
pthread_join(tid,NULL);
return 0;
}
void *fibonacci(void *param, int numbers[])
{
int it, IT_MAX;
printf("Entering Child Thread:\n");
IT_MAX = atoi(param);
numbers[0] = 0;
numbers[1] = 1;
for (it = 2; it < IT_MAX; ++it)
{
numbers[it] = (numbers[it - 1] + numbers[it - 2]);
}
for (it = 0; it < IT_MAX; ++it)
{
printf("%d\n", numbers[it]);
}
printf("Exiting Child Function.\n");
}
void *runner(void *param)
{
int it, IT_MAX;
int numbers[IT_MAX];
pthread_t tid;
pthread_attr_t attr;
printf("Entering Parent Thread:\n");
pthread_attr_init(&attr);
pthread_create(&tid, &attr, fibonacci(param, numbers), NULL);
pthread_join(tid, NULL);
IT_MAX = atoi(param);
for (it = 0; it < IT_MAX; it++)
{
printf("%d\n", numbers[it]); // I suspect the program breaks here
// It produces a segfault rather than this
}
printf("Leaving Parent Thread\n");
}
The question I have, if it is not clear from above, is what am I doing wrong. I am using gcc, and have been using the -Wall -Werror and -lpthread. -Werror keeps throwing "Control Structure going to end of non-void function", but nothing has anything to say about what can be causing the segfault. As before, I looked for the last hour for a question or article that addresses this, so if this is a dupe, please point me to the question or article in which it is addressed. Thanks to anyone in advance for their help.
One of your problems is in this line:
pthread_create(&tid, &attr, fibonacci(param, numbers), NULL);
Instead of starting a thread with the fibonacci() function, this calls the fibbonacci() function in the current thread and passes the result to pthread_create() as the thread start function. fibonacci() doesn't return a function pointer, so this new thread will crash the program.
You need to just pass fibonacci as the third parameter.
Futhermore, fibonacci() must be declared as void *fibonacci(void *) in order to be used as a thread start function. If you want to pass two parameters, you'll need to place them into a struct and pass a pointer to that.
This pair of lines is also problematic:
int it, IT_MAX;
int numbers[IT_MAX];
IT_MAX is an uninitialised variable, and you use it here to define the size of the numbers[] array. That could also be leading to your crash.
This line
pthread_create(&tid, &attr, fibonacci(param, numbers), NULL);
does not pass the address of fibonacci() to pthread_create() but calls fibonacci(param, numbers)and passes the result returned to pthread_create() as 3rd argument.

Return code from pthread_create() is 11

I am trying to run a simple multi threaded programming and i am getting this error from gcc
return code from pthread_create() is 11
how do i solve this issue ?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 20000
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
Well, you could start with determining what the error actually means. According to this and this (other resources will tell you the same information, this is just an example), the number 11 stands for EAGAIN which in turn means "The system lacked the necessary resources to create another thread, or the system-imposed limit on the total number of threads in a process PTHREAD_THREADS_MAX would be exceeded.".
That matches the fact that your are trying to create 20.000(!) threads. Create less threads, or wait until threads complete before starting new ones.
Note that the maximum number of threads that can be created depends on your system (and possibly even depends on a number of other settings). Google for "How to Find PTHREAD_THREADS_MAX" if you really need to know.
However, unless this is just a trivial example for toying around (or maybe even then) you might want to look into the concept of thread pools and queues.

Creating multiple threads and invoking other exectuables in Cygwin through system()?

I am working on a project in Cygwin. In an attempt to create multiple threads in C, and each thread calls another executable through the command line using the system() function, it turns out things are not working properly. Specifically, the code I have is like this:
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
system("date ");
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
But it does not work. The error I get is segmenetation fault with stack overflows. Anyway has an idea on how to call other executables in the system shell in parallel by creating multiple threads?
Thanks.
Add this code :
for(t=0; t<NUM_THREADS; t++){
pthread_join(threads[t], NULL);
}
before
pthread_exit(NULL);
as called in main().
Several bugs here:
In the main() function, after you create the thread, you should use pthread_exit() to exit from all the individual thread. So exit() use is not right here.
In the end of the main() function, just before you terminate the main thread, call pthread_join() to wait for all the individual thread to terminate.
At the end after all the child threads have terminated, you can call exit() to terminate the process itself.
http://www.thegeekstuff.com/2012/04/terminate-c-thread/
That issue looks worth reporting to the Cygwin mailing list.
What you can do instead is to do away with threads and use fork()/exec() or spawn(_P_NOWAITO, ...) to create the child processes.
(spawn() actually is a family of functions; see /usr/include/process.h for details. Its use is recommended as it avoids Cygwin's high fork overhead.)

Resources