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]. */
Related
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.
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(...).
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);
...
}
I am trying to create a thread library and my thread is a struct type. Have to follow a certain interface and in that I need to pass the thread by value. For ex: to join on a thread my code is as follows:
int thread_join(thread_t thread, void **status1)
{
printf("Joining thread\n");
long int thId = thread.id;
printf("Thread id: %ld\n", thId);
gtthread_t * thrd = getThreadFromID(thId);
while(thrd->status != EXIT)
{
}
status1 = &(thrd->ret_value);
return 0;
}
And I an passing a struct of type thread_t to this function. My problem is when I see the thread's ID in the calling function, its displayed properly but when I check it in the thread_join function its displayed as 0. The caller function is as follows:
void* caller(void* arg)
{
thread_t th;
thread_create(&th, some_function, NULL);
thread_join(th, NULL);
while(1);
}
Thread create initializes the ID of the thread to a non-zero value and starts the function associated with it.
My thread structure (and other relevant structure is):
typedef enum
{
RUNNING,
WAITING,
CANCEL,
EXIT
} stat;
//Thread
typedef struct
{
ucontext_t t_ctxt;
long int id;
stat status;
void * ret_value;
int isMain;
} thread_t;
int thread_create(thread_t *thread, void *(*start_routine)(void *), void *arg)
{
thread = (thread_t *)malloc(sizeof(thread_t));
thread->id = ++count;
thread->status = RUNNING;
thread->ret_value = NULL;
thread->isMain = 0;
if(getcontext(&(thread->t_ctxt)) == -1)
handle_error("getcontext");
thread->t_ctxt.uc_stack.ss_sp = malloc(SIGSTKSZ);
thread->t_ctxt.uc_stack.ss_size = SIGSTKSZ;
thread->t_ctxt.uc_link = &sched_ctxt;
makecontext(&thread->t_ctxt, (void (*)(void))wrap_func, 2, (void (*)(void))start_routine, arg);
enqueue(gQ, thread);
printf("Thread id: %ld\n", thread->id);
swapcontext(&(curr_thread->t_ctxt),&sched_ctxt);
return 0;
}
Why does this happen? After all, I am passing by value and this should create a copy of the thread with the same values. Thanks.
EDIT:
Basically I am having a queue of threads and there is a scheduler which round-robins. I can post that code here too but I'm sure that's needless and that code works fine.
EDIT2:
I am making a header file from this code and including that header in another file to test it. All my thread_t variables are static. The caller is a function which includes my header file.
What is this line:
thread = (thread_t *)malloc(sizeof(thread_t));
for?
You pass in to thread_create() an address which referrs to a struct thread_t defined in caller() as auto variable.
Doing as you do, you allocate memory to the pointer passed in to thread_create() initialise it and forget the address on return.
The code never writes to the memory being referenced by the address passed in! Besides this it is a memory leak.
To fix this simply remove the line of code quoted above.
You have no mutex guard on thread id getter. Presumably, there is no guard on setter. What can be happening is that the variable is not visible in the other thread yet. And, without a critical section, it may never become visible.
Each variable which is accessed for both read and write from different threads has to be accessed in a critical section (pthread_mutex_lock / unlock).
Another possibility is that you are setting the thread id inside the running thread and you are accessing the variable even before it is set. If you attempt to join immediately after starting a thread it is possible, that the other thread hasn't been run at all yet and the variable is not set.
side note: do yourself a favor and use calloc:)
In caller function,
thread_create(&th, some_function, NULL);
should be
gtthread_create(&th, some_function, NULL);
I'm learning about threads now. I'm wondering if it is possible to pass a variable to my thread. My assignement is to create a thread and assign a number (a name if you will) to each thread and print the number every 100ms. my current program is as below :
#define PCHECK(sts,msg) if((sts)!=0){printf("error : %s\n",msg); exit(EXIT_FAILURE)}
#define NB_THREAD 5
void* do_nothing(void* data)
{
int i;
//printf("creation thread %d",(int)data);
while(1)
{
usleep(100000);
printf("thread number : %d \n",data);
}
i = 0;
pthread_exit(NULL);
//exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
{
int pid, j, status;
pthread_t thread;
int * res;
int stat;
for (j = 0; j < NB_THREAD; j++)
{
stat = pthread_create(&thread, NULL, do_nothing, (void *) j );
if (stat !=0)
{
perror ("pthread_create()");
}
}
for (j = 0; j < NB_THREAD; j++)
{
pthread_join(thread, (void **) &res );
}
return EXIT_SUCCESS;
}
for the moment the only number getting printed is 0 (the value of data). Can someone point out where did i went wrong thanks :)
Here are some good examples of how to pass arguments to pthreads
[1] https://computing.llnl.gov/tutorials/pthreads/#PassingArguments
I suspect that your problem might be that your running this on a 64-bit system that uses 32-bit int types. So data is a 64-bit void* type but in your thread function you're printing it out as a 32-bit int:
// example assumes that this thread instance was started by
// pthread_create(&thread, NULL, do_nothing, (void *) j ) when
// j == 1
printf("thread number : %d \n",data);
^ ^
| +-------- passing a 64-bit pointer 0x00000000.00000001
|
+---------------- treats the pointer argument as a 32-bit int and
happens to only see the all-zero 32-bits
I suspect that you'll get the output you expect if you change the printf() to:
printf("thread number : %d \n", (int) data);
As a general rule, when writing thread functions I think it's a good idea to have the first actions of the thread function be to convert the data item passed to the thread function to the type that was actually passed to pthread_create():
void* do_nothing(void* data)
{
int id = (int) data; // `pthread_create()` was passed an `int`
// `data` is not used again after this point
// ...
}
A few other points
if you pass an actual pointer to data to the thread function, make sure that each thread gets their own separate copy (unless the data is supposed to be the same instance for each thread, which is possible but uncommon).
if you're spinning up multiple threads you either need to keep each pthread_t object returned by pthread_create() (in an array, maybe) so you can join on them later, or you need to call pthread_join()/pthread_detach() before reusing the pthread_t object so that the system can clean up any resources it has allocated for that thread when the thread finished running. In the example as posted that might not matter much because the threads will run forever (or until something kills the process). The pthread_join() call you have will never complete successfully.
But the following code is destined to break when you change things so the thread function stops after some amount of time:
for (j = 0; j < NB_THREAD; j++)
{
pthread_join(thread, (void **) &res );
}
Because thread only has the pthread_t for the last thread created, once it successfully joins it's not valid to use any more. The next loop iteration will try to join a thread that's already been joined and is no longer valid.