I have an issue with threads.
I am defining a global variable, a char * that I initialize to NULL, and a mutex.
pthread_mutex_t mutex;
char *minURLTime;
minURLTime = NULL;
Then I initialize my mutex:
pthread_mutex_init(&mutex, NULL);
I then create a new thread:
void *status;
pthread_t t;
pthread_create(&t, NULL, executeThread, (void *) &val);
pthread_join(t, &status);
And inside that function I allocate space for minURLTime using strdup and copy a string from link:
pthread_mutex_lock(&mutex);
minURLTime = strdup(link);
pthread_mutex_unlock(&mutex);
As I am using the heap (through strdup, which calls malloc), I do not understand why minURLTime is not NULL until the thread is exited, but then it is NULL.
pthread_exit(NULL);
Once pthread_exit is called, although minURLTime is a global variable that was allocated through strdup (which calls malloc), it appears to be NULL. I don't understand, could anyone please explain me?
Thank you very much,
EDIT:
A little more detail.
From main():
void *status;
pthread_t t;
pthread_create(&t, NULL, executeThread, (void *) &val);
pthread_join(t, &status);
ExecuteThread function:
void *
executeThread( void *val )
{
executeRequest(*((int *) val));
if (minURLTime != NULL) {
pthread_mutex_lock(&mutex);
fprintf(stderr, "\nURL AFTER THREAD ( BEFORE EXIT ): %s\n", minURLTime); // Not executed
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
fprintf does not get executed (BEFORE returning pthread_exit).
executeRequest Function:
void
executeRequest( int val )
{
/* some code */
pthread_mutex_lock(&mutex);
minURLTime = strdup(link);
pthread_mutex_unlock(&mutex);
if (minURLTime != NULL) {
pthread_mutex_lock(&mutex);
fprintf(stderr, "\nURL: %s\n", minURLTime); // This one DOES print
pthread_mutex_unlock(&mutex);
}
}
This may be helpful. It prints inside executeRequest, but not inside executeThread, before the thread exited.
Jary
You aren't waiting in the main thread for the new thread to complete, so you're seeing the null before the thread gets around to setting something else. Also, since you haven't protected the variable with a lock, or declared it volatile, the compiler might even have optimized out noticing that the thread changed it.
My apologies, I realize what the problem was, it was something inside executeRequest that was messing up with those variables, I really don't know how it could have overwritten exactly THAT part of memory, but it is fixed. Thank you and sorry!
Related
Can somebody please explain why the following loop for thread creation fails without the sleep function call?
for(t=0; t<NUM_THREADS; t++) {
printf("Main: creating thread %d\n", t);
rc = pthread_create(&thread[t], NULL, BusyWork, (void *)&t);
sleep(1);
if (rc) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
}
If sleep is not inserted then thread function seems to take as an argument
an arbitrary integer between 0 ad NUM_THREADS.
I'm running this on an Ubuntu machine.
Because you are passing t as a pointer, then change t after creating the thread. So each thread refers to the same variable. Which also is a great candidate for race condition bugs. Simply don't do that.
Instead create a hard copy per thread:
type* tmp = malloc(sizeof(t));
memcpy(tmp, &t, sizeof(t));
pthread_create(&thread[t], NULL, BusyWork, tmp);
...
void* BusyWork (void* arg)
{
...
free(arg);
}
You're passing the same pointer to each thread, but still expecting each to see different values, which is not how things work.
I don't think it's a good idea to let the main program end without doing anything to collect/join the threads back together, either.
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(...).
My command line tool keeps throwing the bus error: 10 message. Xcode debugger shows EXC_BAD_ACCESS message and highlights the function call that creates the thread. Manual debugging shows that the execution flow breaks at random positions inside the thread flow. I tried another compiler (gcc), but it ended up the same. Disabling pthread_mutex_lock() and pthread_mutex_unlock() doesn't help. I wrote this small example that reproduces the error.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
typedef struct thread_args {
pthread_mutex_t* mutex;
} thread_args;
void* test(void* t_args) {
printf("Thread initiated\n");
thread_args* args = (thread_args* )t_args;
printf("Args casted\n");
pthread_mutex_lock(args->mutex);
printf("Mutex locked\n");
pthread_mutex_unlock(args->mutex);
printf("Mutex unlocked\n");
pthread_exit(NULL);
}
int main() {
pthread_mutex_t mutex1;
pthread_mutex_init(&mutex1, NULL);
thread_args args;
args.mutex = &mutex1;
pthread_t* thread;
printf("Initiating a thread\n");
pthread_create(thread, NULL, test, &args);
return(0);
}
I think, in your case,
pthread_create(thread, NULL, test, &args);
at this call, thread is a pointer and not allocated memory. So, essentially pthread_create() tries to write into uninitialized memory, which creates undefined behavior.
Referring the man page of pthread_create()
Before returning, a successful call to pthread_create() stores the ID of the new thread in the buffer pointed to by thread;....
Instead, you can do
pthread_t thread;
...
pthread_create(&thread, NULL, test, &args);
You're using an uninitialized pointer to your pthread_t. The actual storage of the pthread_t needs to be somewhere!
Try :
int main() {
pthread_mutex_t mutex1;
pthread_mutex_init(&mutex1, NULL);
thread_args args;
args.mutex = &mutex1;
pthread_t thread;
printf("Initiating a thread\n");
pthread_create(&thread, NULL, test, &args);
return(0);
}
As other answers pointed out, you need to initialize your pointer thread which you can simply do with:
pthread_t thread;
pthread_create(&thread, NULL, test, &args);
Well, then I'll have to allocate memory dynamically, because different
threads are spawned inside many different functions, hence I can't use
local variables, because I'm not going to join the threads. Then, how
can I free the allocated memory without waiting for the thread to
finish, i.e. without calling join?
No. You don't need to dynamically allocate just because you are going to spawn multiple threads. The thread identifier is no longer needed once a thread has been created So whether it's a local variable or malloced is not important. It's only needed when you need to join or change some characteristics of the thread -- for which you need the ID. Otherwise, you can even reuse the same thread for creating multiple threads. For example,
pthread_t thread;
for( i = 0; i<8; i++)
pthread_create(&thread, NULL, thread_func, NULL);
is perfectly fine. A thread can always get its own ID by calling pthread_self() if needed. But you can't pass a local variable mutex1 to thread functions as once main thread exits, the mutex1 no longer exits as thread created continues to use it. So you either need malloc mutex1 or make it a global variable.
Another thing to do is that if you decide to let the main thread exit then you should call pthread_exit(). Otherwise, when the main thread exits (either by calling exit or simply return) then the whole process will die, meaning, all the threads will die too.
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);