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.
Related
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'm trying to create a detached thread so I won't need to free the memory allocated for it.
Valgrind is used to check for memory leaks.
I've used IBM example and written:
void *threadfunc(void *parm)
{
printf("Inside secondary thread\n");
return NULL;
}
int main(int argc, char **argv)
{
pthread_t thread;
int rc=0;
rc = pthread_create(&thread, NULL, threadfunc, NULL);
sleep(1);
rc = pthread_detach(thread);
return 0;
}
this works and doesn't create leaks, but a version without "sleep(1);" doesn't.
Why is this sleep(1) needed?
I'm trying to create a detached thread so I won't need to free the
memory allocated for it.
In this case, pthread_detach() is not be required and hence should not be used. Additionaly, in this code snippet you have not done any explict memory allocation, so you should not worry about the freeing the memory.
Why is this sleep(1) needed?
When you create the new thread, parent and child threads can starts executing in any order.
Its depends on the OS schedular and other factors. Now in this case if parent threads gets
scheduled first then it is possible that its goes and exit the program before child thread
starts execution.
By adding sleep in the parent context, the child thread is getting time to start and finish the execution before finished. But this is not good idea and as we do not know how much time child thread will take. hence pthread_jon() should be used in the parent context. For detailed information please refer to POSIX thread documentation and great arcicle from below link
https://computing.llnl.gov/tutorials/pthreads/
I am running two separate threads in C, both doing some operations. Both threads include infinite loop. When I run this program couple of times, I always get a memory leak error.
*** glibc detected *** ./a.out: free(): invalid next size (normal): 0x08652510 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6c501)[0x3d1501]
...
I believe it is a memory error, the problem is, when I always need to stop that program(cause im still testing it), i just terminate the program with Ctrl+C, so I believe I always miss the free(anything) command, which then causes the error.
Can you tell me how to avoid this situation? So I can free() memory even in case I terminate the program?
Next thing which comes to my mind is, when i wait a couple of minutes and then run the program again, it runs perfectly again
Thanks for any hints
void *lineOne(void *dataO)
{
struct IPlist *IPlist = dataO;
static struct ARP_entryI ARP_tableI[ARP_TABLE_SIZE];
int neigh=0; //pocet susedov
int neigh1=0; //stav pred tym
int i;
getAddress();
while(1)
{
while (neigh == neigh1)
{
neigh =rcvBroad(IPlist, neigh);
}
neigh1=neigh;
for (i=neigh ; i<neigh+1; i++)
{
main_client(ARP_tableI, IPlist[i-1].IPaddr); // vysle tcp, prijme arp
getAddress();
}
}
}
//pocuvaServer, odpoveda ARP
void *lineTwo()
{
static struct ARP_entryO ARP_tableO[ARP_TABLE_SIZE];
int line = from_local_arp(ARP_tableO);
main_server(ARP_tableO, line); // pocuva tcp, vysle arp
}
void main()
{
static struct IPlist *IPlist[ARP_TABLE_SIZE];
pthread_t thread1, thread2;
int iret1, iret2;
/* Create independent threads each of which will execute function */
iret1 = pthread_create( &thread1, NULL, lineOne, (void *)IPlist); //(void *) &
iret2 = pthread_create( &thread2, NULL, lineTwo, NULL);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
}
you could handle SIGINT, but it doesn't matter, your code already corrupts the memory by the time you want to do that extra free() call.
to find the problem compile it with -g and run it with valgrind.
Try running your program through Valgrind and see if you can get any help on where the memory allocation structure is corrupted. From the error it looks like you are somewhere doing something invalid with the memory allocation the corrupts the internal data structures for memory allocation.
use a signal handler to catch the Ctrl-C event (Ctrl-C generates a SIGINT signal), and set a flag in the handler. modify the infinite loop so that it stop looping when it sees the flag, and write a cleanup code after the loop. your program will then end "normally".
the signal handling functions are part of the GNU C library (and of any POSIX system, i think). here is a link to the documentation of the gnu c library regarding signal handling.
You have corrupted your heap space. Perhaps you are writing off the end (or before the beginning) of a chunk of allocated memory. The free is detecting the corruption and producing the error.
When the program is terminated all memory will be freed automatically.
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.)
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.