Simple pthread prog: segmentation fault - c

Trying to see how pthread works by running a simple program but I am getting segmentation fault (core dumped) at pthread_create
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void* testfunc(void* arg) {
while (1) {
printf("testfunc");
}
}
int main(void) {
printf("helo\n");
if (pthread_create(NULL, NULL, &testfunc, NULL) != 0) {
perror("pthread failed to create\n");
}
while (1) {
printf("main function\n");
sleep(1000);
}
return 0;
}
What seems to be causing the problem? I am on Ubuntu 20.04 if that matters.

You can't pass NULL for pthread_create's first argument.
Before returning, a successful call to pthread_create() stores the ID of the new thread in the buffer pointed to by thread
Also, pthread_create doesn't set errno, so using perror makes no sense, at least not without some prep.
on error, it returns an error number, and the contents of *thread are undefined.
Fixed:
pthread_t thread;
if ( ( errno = pthread_create(&thread, NULL, &testfunc, NULL) ) != 0 ) {
perror("pthread failed to create\n");
}
...
pthread_join(thread, ...); // Normally.

Threads in c are very unforgiving. There are a few problems with your code that I can see.
First you might want to refer to the developer docs for p_thread. They are very well documented. What you currently have is a thread call but you are not pointing anything to that thread. This is why you are receiving the segmentation error. Meaning your program lost the pointer to that thread somewhere when it tried calling it. I suggest something like.
pthread_t thread;
int * argument = 5;
if(pthread_create(&thread,NULL, &testfunc, &argument) !=0){
// ^This is a pointer to your argument
// that you want to pass in
perror("pthread failed to create\n");
exit(1);
}
and your thread function will also need to be typecast from a void pointer into whatever you want it to return to work with. Then it needs to be cast back to a void pointer before is returned from the thread routine.
void* testfunc(void* arg){
int* testVar = (int *)arg;
// do some logic here
return (void *) testVar;
}
lastly you are responsible for your memory in C so you must kill the thread you created before exiting.
pthread_join(thread, NULL);
My number one suggestion is you watch some videos relating to it.

Related

Is it possible to create threads in multiple files to be executed in main file?

I have the following structure to want to interact with a sorter (infinite loop) and networker (infinite loop) on 2 separate threads. The threads are generated in each of their respective files instead of the main file. Are there any issues with this?
main.c
int main(void {
network();
sorter();
}
sort.c // creates random array then sorts them in a continuous while loop (never ending)
void sorter() {
int r1 = pthread_create(&thread1, NULL, (void *) &sorter, NULL);
pthread_join(thread1, NULL);
}
int* getArray() { ... }
int getElement() { ... }
network.c
void network() {
int r2 = pthread_create(&thread2, NULL, (void *) &startNetwork, NULL);
pthread_join(thread2, NULL);
}
void startNetwork() {
int sockfd, portno, optval, n;
socklen_t adSize;
struct sockaddr_in servAd, clientAd;
...
while(1) {
//receive packet
int *arr = getArray();
// send packets
// or receive packet that has a command to get array
}
}
Is it possible to have the threads structured like that? Will my main file freeze because the thread is not being created in the main file? Is there a better way to do this?
The main issues with sorter() are (1) that it won't return until the thread function returns, and (2) the thread function is sorter(), so you have an indefinite loop. This is likely a problem with trying to abstract your code into the question. There are nitty-gritty details to fix up like the types of the functions, etc.
The issues with network() might be similar or different; you've not shown the function you call from main(), so it is not clear what you intend. The code in networker() is not good; it makes pthread_create() call a function with an incorrect signature — thread functions should have the signature void *function(void *arg);.
However, in general, there is no problem with starting different threads in code from different source files. If the threads are not detached — if you're going to join them — then you'll need to make the pthread_t initialized by pthread_create() available for the code that manages the joining — possibly because they're in global variables or part of a global array, or possibly because you provide functional access to private data stored in the separate source files.
So, you might have:
network.c
static pthread_t thread2;
static void *network_thread(void *arg);
void network(void)
{
if (pthread_create(&thread2, NULL, network_thread, NULL) != 0)
…handle error…
}
void network_join(void)
{
void *vp = 0;
if (pthread_join(&thread2, &vp) != 0)
…report error…
…maybe use the return value in vp…
}
sorter.c
static pthread_t thread1;
static void *sorter_thread(void *arg);
void sorter(void)
{
if (pthread_create(&thread1, NULL, sorter_thread, NULL) != 0)
…handle error…
}
void sorter_join(void)
{
void *vp = 0;
if (pthread_join(&thread1, &vp) != 0)
…handle error…
…maybe use value in vp…
}
main.c
#include "sorter.h"
#include "network.h"
int main(void)
{
network();
sorter();
network_join();
sorter_join();
return 0;
}
You would probably build checks into network_join() and sorter_join() such that if you've not already called network() or sorter(), the code won't try to join an invalid thread.
Are there any issues with this?
It looks like maybe you do not understand what pthread_join(thread1) does. It does nothing, except wait until thread1 is finished. But you said that the network thread and the sorter thread are meant to run forever, so that's going to be a long wait:
For future reference, pthread_join() is meant to be used like this:
pthread_create(&thread1, attrs, f, arg);
doSomethingElse(...);
pthread_join(thread1, NULL);
doOtherStuff(...);
The original thread starts the new thread, and then it does something else while the new thread is calling f(arg). Then, after the f(arg) call and the doSomethingElse(...) call have both completed, the original thread goes on to doOtherStuff(...).

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.

pthread_join causes segmentation error (simple program)

I am just trying to work with multi-threaded programs, but I am having problems with the pthread_join function. The code below is just a simple program I am using to show pthread_join crashing. The output from this code will be:
before create
child thread
after create
Segmentation fault (core dumped)
What causes pthread_join to give a segmentation fault?
#include <pthread.h>
#include <stdio.h>
void * dostuff() {
printf("child thread\n");
return NULL;
}
int main() {
pthread_t p1;
printf("before create\n");
pthread_create(&p1, NULL, dostuff(), NULL);
printf("after create\n");
pthread_join(p1, NULL);
printf("joined\n");
return 0;
}
Because in your call to pthread_create you actually call the function, and as it returns NULL pthread_create will fail. This will not properly initialize p1 and so will (probably) cause undefined behavior in the pthread_join call.
To fix this pass the function pointer to the pthread_create call, do not call it:
pthread_create(&p1, NULL, dostuff, NULL);
/* No parantehsis --------^^^^^^^ */
This should also teach you to check the return values of function calls, as pthread_create will return non-zero on failure.
You need to fix your function type and the way you call pthread_create:
void * dostuff(void *) { /* ... */ }
// ^^^^^^
pthread_create(&p1, NULL, dostuff, NULL);
// ^^^^^^^

pthread array of pointers

I have a struck with an array of pthread pointers. Each thread is meant to read a different data stream
typedef struct {
// ...other stuff
pthread_t *threads[MAX_STREAM_COUNT];
} stream_manager;
And when I want to start reading:
void start_reading(stream_manager *sm, int i) {
// do some pre processing stuff
pthread_create( (pthread*) &sm->threads[i],
NULL,
read_stream_cb,
(void*) sm->streams[i] );
}
When I want to stop reading:
void stop_reading(stream_manager *sm, int i) {
iret = pthread_join(*sm->threads[i], NULL);
if(iret != 0) {
perror("pthread_join returned with error:: ");
printf( "pthread_join returned with error:: %s\n", strerror(iret) )
}
}
For now, my read_stream_cb function simply prints the name of the stream its reading from.
void* read_stream_cb(stream *strm) {
stream *s = (stream*) strm;
prinf("%s\n", s->name);
}
In the main program, I initialize 2 streams with different names. I call run start_reading(), sleep(3) and stop_reading()). The program prints the stream names fine for 3 seconds, but the pthread_join does not return successfully. It returns 3 and prints out
pthread join error: Operation timed out
pthread_join returned with errer:: No such process
I think this may be a pointer issue? I may just be confused with order of operations with these pointers in the join pthread_join(*sm->streams[i], NULL); . I'll look into that more.
pthread_create() takes a pthread_t* as its argument, this is passing a pthread_t**:
pthread_create( (pthread*) &sm->threads[i],
as sm->threads is an array of pthread_t*. Change stream_manager to:
typedef struct {
// ...other stuff
pthread_t threads[MAX_STREAM_COUNT]; /* No longer array of pointers. */
} stream_manager;
and remove the unnecessary cast from the call to pthread_create().
pthread_join() takes a pthread_t:
pthread_join(sm->threads[i]); /* Not sm->streams[i]. */

Segfault when dereferencing pointer set by pthread_join

I have the following code for testing how to "implement return values" using pthread_exit() and pthread_join().
#include <stdio.h>
#include <pthread.h>
void* busy() {
int returnValue = 2;
pthread_exit((void*)&returnValue);
}
int main() {
void* retVoidPtr = NULL;
int* retValPtr = NULL;
int retVal;
pthread_t busyThread;
pthread_create(&busyThread, NULL, busy, NULL);
pthread_join(busyThread, &retVoidPtr);
retValPtr = (int*) retVoidPtr;
retVal = *retValPtr;
printf("Busy thread returned %d\n", retVal);
return 0;
}
The program compiles fine, but never gets to the printf statement. A segfault occurs at the line retVal = *retValPtr. Using gdb, I can see that the retValPtr pointer is no longer NULL but when I try print *retValPtr gdb says "Cannot access memory at address 0x...". Any suggestions where I'm going wrong?
A C function can't return a pointer to a value on the stack under the best of circumstances. If that stack is the stack of a thread that has terminated, though, we're talking complete disaster, as the memory for that thread's stack may no longer be mapped -- that appears to be the case here.
Your thread function needs to return a pointer to data that will remain valid when the thread terminates: a global variable, or a block obtained from malloc().

Resources