Below program gives me segmentation fault(core dumped) error on random instances. sometimes it runs without any error. The program is just for understanding deadlocks.
Even though I have run this program for about 15 times, I haven't faced a deadlock so far. Sometimes the program runs smoothly(which can be expected) and sometimes it gives the segmentation fault(which is not expected). Why do I get the segmentation fault?
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int a=5;
int b=3;
pthread_mutex_t mutex1,mutex2;
void* add_subtract(){
pthread_mutex_lock(&mutex1);
pthread_mutex_lock(&mutex2);
a=a+2;
b=b-2;
printf("%d %d\n",a,b);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
}
void* subtract_add(){
pthread_mutex_lock(&mutex2);
pthread_mutex_lock(&mutex1);
b=b-2;
a=a+2;
printf("%d %d\n",a,b);
pthread_mutex_unlock(&mutex1);
pthread_mutex_unlock(&mutex2);
}
int main(){
pthread_t thread1,thread2;
pthread_create(&thread1,NULL,add_subtract(),NULL);
pthread_create(&thread2,NULL,subtract_add(),NULL);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
return 0;
}
When you pass add_subtract() as an argument, you're calling the function and then passing the return value as the argument. In this case you want to pass the function itself... try it without the parens.
I think you need to initialize the mutex: http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_mutex_init.html
The pthread_mutex_init() function initialises the mutex referenced by
mutex with attributes specified by attr. If attr is NULL, the default
mutex attributes are used; the effect is the same as passing the
address of a default mutex attributes object. Upon successful
initialisation, the state of the mutex becomes initialised and
unlocked.
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 am new in threads in c. My code has a thread that increasing a counter and occasionally(randomly) another thread reads that counter. I used mutex in this code but my code always gives me value equal to 1. Although I used pthread_mutex_unlock but it seems the value becomes lock for ever. what should I do to solve the problem?
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <pthread.h>
///////////////////////////
long int count=0;
int RunFlag=0;
pthread_mutex_t mtx;
void *readfun(void *arg)
{
while (RunFlag==0)
{
pthread_mutex_lock(&mtx);
count=count+1;
pthread_mutex_unlock(&mtx);
}
}
void *printfun(void *arg)
{
int RadnTime=0;
for (int j=0;j<4;j++)
{
RadnTime=rand()%3+1;
sleep(RadnTime);
printf("The current counter after %d seconds is: ",RadnTime);
pthread_mutex_lock(&mtx);
printf("%d\n",count);
pthread_mutex_unlock(&mtx);
}
}
void main ()
{
pthread_t thread1;
pthread_t thread2;
pthread_mutex_init(&mtx, NULL);
pthread_create(&thread1,NULL,readfun,NULL);
pthread_create(&thread2,NULL,printfun,NULL);
//stop the counter
RunFlag=1;
pthread_exit(NULL);
}
You are setting RunFlag immediately after the two threads are created, so readfun barely has any time to execute. RunFlag=1; should be at the end of printfun.
As far as I know, reading from and writing to RunFlag isn't guaranteed to be atomic, so access to it should be protected as well. I don't see a problem happening here (given the values in question), but you are entering undefined behaviour territory.
Your functions don't return anything even though they are declared as returning void*. Add return NULL; to them.
Finally, the second %d should be %ld since count is a long int.
Note that
pthread_mutex_t mtx;
pthread_mutex_init(&mtx, NULL);
can be replaced with
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
1) You also have data race as two are accessing RunFlag. So, you need to protect it with synchronization primitive (such as mutex or use a semaphore).
But you don't need the RunFlag for this purpose. Since you can use an infinite loop in readfun() thread and then simply call _exit() from printfun() thread to exit the whole process.
2) Thread functions must return a pointer to satisfy by pthread_create()'s requirement. But you thread functions don't return anything. You can add return NULL; at the end of both thread functions.
Be aware of signed integer overflow as count could potentially overflow.
I am writing a program to test my understanding of condition variables. Basically, thread 0 checks if count is even, and if so, increments it. If not, then it signals thread 1 which increments the count variable. The process continues until count reaches 15. Here is my code:
#include <pthread.h>
#include <stdio.h>
#define numThreads 2
int count=0;
pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv;
void *checkEven(void *threadId)
{ while(count<=15){
//lock the mutex
pthread_mutex_lock(&count_mutex);
printf("even_thread: thread_id=%d count=%d\n",threadId,count);
if(count%2==0){
count++;
}
else{
printf("Odd count found, signalling to odd thread\n");
pthread_cond_signal(&count_threshold_cv);
}
pthread_mutex_unlock(&count_mutex);
sleep(1);
}
}
void *checkOdd(void *threadId)
{
pthread_mutex_lock(&count_mutex); //obtain a lock
while(count<=15){
pthread_cond_wait(&count_threshold_cv, &count_mutex); //wait() relinquishes the lock
count++;
printf("odd_thread: thread_id=%d, count=%d\n",threadId,count);
}
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}
int main()
{
pthread_t threads[numThreads];
int rc;
int a=0;
int b=0;
pthread_create(&threads[0], NULL, checkEven, (void *)a);
pthread_create(&threads[1], NULL, checkEven, (void *)b);
pthread_join(0,NULL);
pthread_join(1,NULL);
pthread_exit(NULL);
}
Can someone tell me why I am getting segmentation fault(core dumped) error with this? I know that this error occurs when one process tries to violate the address space of some other process, but nothing beyond this.Can someone please help? Thanks!
You're passing a zero to pthread_join as the thread you want to join:
pthread_join(0,NULL);
You wanted:
pthread_join(threads[0],NULL);
pthread_join(threads[1],NULL);
You have several other bugs though. For one thing, your checkOdd code calls pthread_cond_wait even when it's that thread's turn.
You don't seem to understand condition variables. Specifically, you seem to think that somehow the condition variable will know whether or not the thing you are waiting for has happened. It does not -- condition variables are stateless. It's your job to keep track of what you're waiting for and whether or not it has happened.
I'm doing a really easy program using pthreads but i keep getting a "Segmentation fault error" and I cannot understand why. The program is to be compiled in C language.
The program should create 3 threads, each of them should print its number and its calling thread number (in this case , i just want 3 threads to say "I'm thread (i) and the calling thread is 0 " since they are all created from the same thread)
The problem, I think, is with the malloc function used to allocate memory to be passed.
In case this is te problem, how can i solve it?
Should I create an array of 3 pointers before the "for" loop, and store in each pointer of this array the two variables i want to pass to the thread? How to actualy do it? I tried but it doesn't seem to work.
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
void *Son (void* arg)
{int *id=(int*)arg; //retrieve array
sleep(id[1]+1);
printf("I'm thread %d , created from %d! \n",id[1],id[0]);
free(arg);
pthread_exit(0);
}
int main()
{pthread_t threads[3];
int i;
for (i=0;i<3;i++)
{int *a= malloc(2*sizeof(int)); // dynamically allocate a variable which will be freed in the thread once executed
a[0]=0; //store i in the content of dynamically allocated a
a[1]=i;
pthread_create(&threads[i],NULL,Son ,(void*)a);
}
int j;
for (j=0;j<3;i++)
{pthread_join(threads[i],NULL);
printf("Joined thread %d",j);
}
printf("THREAD FINISHED\n");
return 0;
}
Here:
for (j=0;j<3;i++)
{
pthread_join(threads[i],NULL);
printf("Joined thread %d",j);
}
you probably wanted to use threads[j] instead of threads[i]. i, at this point is 4 and you are accessing an invalid memory address via the pthread_join. Also, you need to use j++ instead of i++.
I am checking the behavior of 'pthread_join' and have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <pthread.h>
void *thread(void *vargp)
{
pthread_detach(pthread_self());
pthread_exit((void *)42);
}
int main()
{
int i = 1;
pthread_t tid;
pthread_create(&tid, NULL, thread, NULL);
sleep(1);
pthread_join(tid, (void **)&i);
printf("%d\n", i);
printf("%d\n", errno);
}
Observed output on my platform (Linux 3.2.0-32-generic #51-Ubuntu SMP x86_64 GNU/Linux):
with the 'sleep(1)' commented out:
42
0
with the sleep statement, it produces:
1
0
according to the man page of pthread_join, we should get the error 'EINVAL' when we are trying to join a non-joinable thread, however, neither cases above got the errno set. And also in the first case, it seemed that we can even get the exit status of a detached thread, I am confused with the result. Could anyone explain this? Thanks
[EDIT]: I realized that the first printf may reset 'errno', however, even after I swapped the order of the two 'printf' statements, I still got the same results.
Your expectation is wrong. Calling pthread_join on a detached thread invokes undefined behavior. There is no requirement to set errno, return the error code, or even return at all.
In case you need a citation,
The behavior is undefined if the value specified by the thread argument to pthread_join() does not refer to a joinable thread.
Source: http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html
Also, note that most pthread functions, including pthread_join, do not use errno. Instead they return the error code as their return value. As such, inspecting errno after calling a pthread function is wrong even if you didn't invoke undefined behavior when you called it.
You get this error by reading the return value of function pthread_join, try this:
if (errno = pthread_join(tid,NULL)) {
printf("An error ocurred: %i", errno);
}