pthread_join causing seg fault - join

As part of a pthreads tutorial exercise I wrote a program to create 10 threads than to join the 10 threads. The program runs and prints the output however it seems that on the first call to pthread_join it causes a segmentation fault. I am not sure why this is occurring. I tried searching on web, however most issues where concerning invalid pointers passed to the function. I am not sure if this is the same issue with my code, as I am not seeing it easily.
if anyone can help me, I certainly would appreciate it :)
code is below:
#include <stdio.h>
#include <pthread.h>
#define NTHREADS 10
void *thread_function(void *arg)
{
int i;
int *coming = (int*) arg;
for(i=0; i<5; i++)
printf("Hello, World (thread %d)\n", *coming);
return NULL;
}
int main(void)
{
int i;
void *exit_status;
int retVal;
pthread_t pthread_array[NTHREADS];
int randVals[10] = {23,5,17,55,9,47,69,12,71,37};
printf("threads are created\n");
for(i=0; i<10; i++)
{
retVal=pthread_create(&pthread_array[i], NULL, thread_function, &randVals[i]);
printf("pthread_create %d retVal=%d\n", i, retVal);
}
printf("threads are joined\n");
for(i=0; i<10; i++)
{
retVal= pthread_join(pthread_array[i], &exit_status);
printf("pthread_join %d retVal=%d and exit_status=%d\n", i, retVal,
*((int *)exit_status));
}
printf("all threads have ended\n");
return 0;
}

This is the problem
printf("pthread_join %d retVal=%d and exit_status=%d\n", i, retVal,
*((int *)exit_status));
your thread function returns NULL, and so this is the value stored in exit_status. So now in your printf you do this
*((int *)exit_status
you are casting this NULL pointer to a int* and then dereferencing it. Dereferencing NULL pointers is not a good idea. See this question for a fuller example of how to use exit_status What does exactly the "status" in pthread_join represent and how to query it

*((int *)exit_status));
If the thread function returns NULL (which it does), this will try to dereference it. Before doing so, you should test exit_status:
pthread_join(...);
if (exit_status != NULL)
/* Safe to use. */

Related

pthreads - reading and writing to global variables

I am learning about pthreads and I've created a program that creates 10 threads of which 5 read the value of a global variable and 5 update the value of a global variable. Here is some sample output from the program.
My question is why in the write() thread does it always say that the shared variable is 2 even though it is being updated each time a write() thread is created? I would of expected it to change.
Output:
Write thread - shared variable was 2 and it is now 22
Read Thread - The shared variable is 2
Write thread - shared variable was 2 and it is now 9
Write thread - shared variable was 2 and it is now 12
Write thread - shared variable was 2 and it is now 37
Write thread - shared variable was 2 and it is now 43
Read Thread - The shared variable is 2
Read Thread - The shared variable is 43
Read Thread - The shared variable is 43
Read Thread - The shared variable is 43
The code:
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#define NUM_THREADS 5
int shared_varibale = 2;
void *read(void *param);
void *write(void *param);
int main (int argc, char *argv[]) {
int i;
time_t t;
pthread_t tid[NUM_THREADS];
/* Intializes random number generator */
srand((unsigned) time(&t));
/*Create 5 write threads*/
for(i = 0; i < NUM_THREADS; i++) {
pthread_create(&tid[i], NULL, write, &shared_varibale);
}
/*Create 5 read threads*/
for(i = 0; i < NUM_THREADS; i++) {
pthread_create(&tid[i], NULL, read, &shared_varibale);
}
return 0;
}
void *read(void *param) {
int *p = (int*)param;
printf("The variable is %d\n", *p);
pthread_exit(NULL);
}
void *write(void *param) {
int *p = (int*)param;
int rand_varibale = rand() % 50;
printf("Write thread - shared variable was %d and it is now %d\n", *p, rand_varibale);
*p = rand_varibale;
pthread_exit(NULL);
}
First of all, you should not call your own functions read or write because POSIX already uses these identifiers. You should also add error checking to all function calls because it is easy to miss problems if you do not do that.
There is no synchronization in your example, so you have a data race. Among other things, this means that the threads may see an outdated value. And you do not impose any order on the execution of the threads. If your hardware supports that much parallelism, it is likely that all threads execute until the printf call (which causes all of them except one to block). Since the shared variable is only written to after the printf call, you get the results you see.

my process doesn't go to the child process

I have to take a user input number 'n' in the parent process and then pass it to the child process.The child process then takes 'n' user input values and stores them in an array.It then call a thread and send this array as an argument.The thread sums all the values in the array and send it back to the child process which prints it.
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<pthread.h>
#include<fcntl.h>
void *sum(void *a)
{printf("in thread" );
int * arr=(int *)a;
int i;
int sum=0;
int size=sizeof(arr)/sizeof(arr[0]);
for(i=0;i<size;i++)
{
sum=sum +arr[i];
}
pthread_exit(sum);
}
int main()
{
int pipefd[2];
pid_t childpid;
pthread_t tid;
pipe(pipefd);
int r;
int n;
childpid=fork();
if (0==childpid)
{
printf("in child process" );
close(pipefd[1]);
read(pipefd[0],r,sizeof(int));
close(pipefd[0]);
int *ret;
int a[r];
int i;
for (i = 0; i <r; i++)
{ printf("enter values: ");
scanf("%d",&a[i]);
}
pthread_create(&tid,NULL,sum,(void *)a);
pthread_join(tid,(void *)&ret);
printf("%d",*ret );
}
else
{ printf("in parent process" );
printf("enter a number" );
scanf("%d",&n);
close(pipefd[0]);
write(pipefd[1],n,sizeof(int));
close(pipefd[1]);
}
return 0;
}
I have checked this code a dozen of times and nothing seems to be wrong.The process stops after taking the value of 'n'.The child process never runs.
Both read and write expect to receive the memory address of a buffer to use. You need to take the address of the variables you're trying to fill.
E.g.
write(pipefd[1], &n, sizeof(int));
and
read(pipefd[0], &r, sizeof(int));
By the way, the child process most likely is running. It's just your value for r is coming back as 0. Simple debugging trick: Use fprintf(stderr, "stuff to print"); to check your results at various stages. You can easily verify the child process is running, for example.

How Lua deal with the stack?

I'm trying Lua and want to know how lua_State working
code and result:
state.c
#include <stdio.h>
#include "lua/src/lua.h"
#include "lua/src/lauxlib.h"
static void stackDump(lua_State *L){
int i;
int top = lua_gettop(L);
for(i = 1; i<= top; i++) {
int t = lua_type(L, i);
switch(t){
case LUA_TSTRING:
printf("'%s'", lua_tostring(L, i));
break;
case LUA_TBOOLEAN:
printf(lua_toboolean(L, i) ?"true":"false");
break;
case LUA_TNUMBER:
printf("%g", lua_tonumber(L, i));
break;
default:
printf("%s", lua_typename(L, t));
break;
}
printf(" ");
}
printf("\n");
}
static int divide(struct lua_State *L){
double a = lua_tonumber(L, 1);
double b = lua_tonumber(L, 2);
printf("%p\n", L);
stackDump(L);
int quot = (int)a / (int)b;
int rem = (int)a % (int)b;
lua_pushnumber(L, quot);
lua_pushnumber(L, rem);
stackDump(L);
printf("---end div---\n");
return 2;
}
int main(void){
struct lua_State *L = lua_open();
lua_pushboolean(L, 1);
lua_pushnumber(L, 10);
lua_pushnil(L);
lua_pushstring(L, "hello");
printf("%p\n", L);
stackDump(L);
lua_register(L, "div", divide);
luaL_dofile(L, "div.lua");
stackDump(L);
lua_close(L);
return 0;
}
div.lua
local c = div(20, 10)
0x100c009e0
true 10 nil 'hello'
---start div---
0x100c009e0
20 10
20 10 2 0
---end div---
true 10 nil 'hello'
I see lua_State in divide is the same with the main one, but they have different data in stack, How this be done ?
I know the best way to understand this is to read source code of Lua , maybe you can tell me where to find the right place.
Think of lua_State as containing the Lua stack, as well as indices delimiting the current visible part of the stack. When you invoke a Lua function, it may look like you have a new stack, but really only the indices have changed. That's the simplified version.
lua_State is defined in lstate.h. I've pulled out the relevant parts for you. stack is the beginning of the big Lua stack containing everything. base is the beginning of the stack for the current function. This is what your function sees as "the stack" when it is executing.
struct lua_State {
/* ... */
StkId top; /* first free slot in the stack */
StkId base; /* base of current function */
/* ... */
StkId stack_last; /* last free slot in the stack */
StkId stack; /* stack base */
/* ... */
};
Programming in Lua, 2nd Edition discusses Lua states in chapter 30: Threads and States. You'll find some good information there. For example, lua_State not only represents a Lua state, but also a thread within that state. Furthermore, all threads have their own stack.
It gets different data the same way anything gets different data: code changes the data inside of the object.
struct Object
{
int val;
};
void more_stuff(Object *the_data)
{
//the_data->val has 5 in it now.
}
void do_stuff(Object *the_data)
{
int old_val = the_data->val;
the_data->val = 5;
more_stuff(the_data);
the_data->val = old_val;
}
int main()
{
Object my_data;
my_data.val = 1;
//my_data.val has 1.
do_stuff(&my_data);
//my_data.val still has 1.
}
When Lua calls a registered C function, it gives it a new stack frame.

what is wrong with following pthread program?

I am not able to execute pthreads program in c. Please tell me what is wrong with the following program. I am neither getting any error nor expected output.
void *worker(void * arg)
{
int i;
int *id=(int *)arg;
printf("Thread %d starts\n", *id );
}
void main(int argc, char **argv)
{
int thrd_no,i,*thrd_id,rank=0;
void *exit_status;
pthread_t *threads;
thrd_no=atoi(argv[1]-1);
thrd_id= malloc(sizeof(int)*(thrd_no));
threads=malloc(sizeof(pthread_t)*(thrd_no));
for(i=0;i<thrd_no;i++)
{
rank=i+1;
thrd_id[i]=pthread_create(&threads[i], NULL, worker, &rank);
}
for(i=0;i<thrd_no;i++)
{
pthread_join(threads[i], &exit_status);
}
}
thrd_no = atoi(argv[1] - 1); likely doesn't do what you intended; the way argv is normally passed into a new process and parsed into a C array, argv[1] - 1 is probably pointing at \0 (specifically, the \0 at the end of argv[0]). (More generally, indexing backwards off the start of a string is rarely correct.) The result is that atoi() will return 0 and no threads will be created. What did you actually intend to do there?
You are passing the same address &rank to each thread, so id and *id is the same for all your worker-s.
You should better allocate on the heap the address you pass to each worker routine.
You might also include <stdint.h and use intptr_t, e.g.
void worker (void* p)
{
intptr_t rk = (intptr_t) p;
/// etc
}
and call
intptr_t rank = i + 1;
thrd_id[i]=pthread_create(&threads[i], NULL, worker, (void*)rank);
You should learn to use a debugger and compile with all warnings and debug information, i.e. gcc -Wall -g (and improve your code till it gets no warnings, then use gdb)
code segment rank=i+1;
thrd_id[i]=pthread_create(&threads[i], NULL, worker, &rank);
will produce race condition.

Modifying PC in jmp_buf to go to another function

For a user-lever thread library, I need to figure out jumping to a function by modifying PC value stored in jmp_buf.
This is what I have written:
jmp_buf env;
void print (void) {
printf("\nHello World!");
}
static int ptr_mangle(int p) {
unsigned int ret;
asm(" movl %1, %%eax;\n"
" xorl %%gs:0x18, %%eax;"
" roll $0x9, %%eax;"
" movl %%eax, %0;"
: "=r"(ret)
: "r"(p)
: "%eax"
);
return ret;
}
int main() {
int i = setjmp(env);
env[0].__jmpbuf[5] = ptr_mangle(print);
longjmp(env, 2);
return 0;
}
I am trying to modify PC in jmp_buf by setting it to the address of the function I am trying to jump to.
I am getting a segmentation fault.
I am unable to figure out what exactly needs to be done. Do I need to modify SP as well?
Any help would be very much appreciated.
What are you trying to do? Are you not checking for the return value of setjmp? I don't think you are doing this correctly. Have a look at the sample code below to see what would be the output be:
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
void subroutine(jmp_buf);
int main(void)
{
int value;
jmp_buf jumper;
value = setjmp(jumper);
if (value != 0)
{
printf("Longjmp with value %d\n", value);
exit(value);
}
printf("About to call subroutine ... \n");
subroutine(jumper);
return 0;
}
void subroutine(jmp_buf jumper)
{
longjmp(jumper,1);
}
The output would be:
About to call subroutine...
Longjmp with a value of 1.
Which begs the question - why are you trying to modify the IP? It sounds like you overwrote something or the code 'jumped' off into the woods and trampled something and came back with a hard landing i.e. segfault.
The variable env is specifically a struct, do not use an array subscript as you have done. I suspect that is why you got a segfault...
Hope this helps,
Best regards,
Tom.

Resources