This will probably require some looking into, but my question is very simple:
Why is numPassenger always 0 in the parentHandler2() function?
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>
#include <sys/time.h>
#include <math.h>
int getRand()
{
return (rand() % 5001);
}
//////////GLOBAL//////////
const int CAPACITY = 100;
const int MEMSIZE = 1024;
char* sharedmem;
pid_t pid;
int numPassenger;
int numTram;
//////////GLOBAL//////////
//handles SIGALRM, generates passengers, sends SIGUSR1
void parentHandler1()
{
numPassenger = getRand();
sprintf(sharedmem, "%d", numPassenger);
kill(getpid(), SIGUSR1);
}
//handles SIGUSR1, calculates number of trams needed, sends SIGUSR2
void childHandler()
{
double n = atoi(sharedmem);
numTram = (ceil(n/100));
sprintf(sharedmem, "%d", numTram);
kill(pid, SIGUSR2);
}
//outputs
void parentHandler2()
{
int n = atoi(sharedmem);
printf("Passengers: %d, Trams: %d\n", numPassenger, n);
}
int main (int argc, char* argv[])
{
srand(time(0));
key_t key;
int shmemaddr;
//shared memory
key=ftok(argv[0],1);
shmemaddr=shmget(key,MEMSIZE,IPC_CREAT|S_IRUSR|S_IWUSR);
sharedmem = shmat(shmemaddr,NULL,0);
pid = fork();
if ( pid > 0 )
{
//timer
struct itimerval timer;
timer.it_value.tv_sec = 3;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = 3;
timer.it_interval.tv_usec = 0;
setitimer (ITIMER_REAL, &timer, NULL);
signal(SIGALRM, parentHandler1);
signal(SIGUSR1, childHandler);
}
else if ( pid == 0 )
{
signal(SIGUSR2, parentHandler2);
}
//not so busy waiting
while(1) sleep(1);
return 0;
}
https://gist.github.com/4299915
Fork creates a new copy of the current process. Global variables aren't shared between processes. The only memory that is shared between your two processes is the memory returned by shmget. The value of numPassenger is never set in the child process.
Related
I can't understand why in this code I get a deadlock.
I have defined this mutexes:
mutex3: = 0 (LOCKED)
mutex2: = 1 (UNLOCKED)
I have 2 processes: Father and son. Each has N threads that I pass by argument. The child's threads contend with the father's threads a "resource" (typical producer / consumer problem).
Thanks in advance!
I suppose the problem is here:
void * func_padre(void * n)
{
while(1)
{
pthread_mutex_lock(&mutex2);
printf("Scrivi messaggio: ");
fflush(stdout);
scanf("%[^\n]",(char *)addr_mem);
getchar();
pthread_mutex_unlock(&mutex3);
}
}
void * func_figlio(void * n)
{
while(1)
{
pthread_mutex_lock(&mutex3);
write(fd,addr_mem,4096);
lseek(fd,0,SEEK_SET);
memset(addr_mem,0,4096);
pthread_mutex_unlock(&mutex2);
}
}
CODE:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
void * addr_mem;
pthread_mutex_t mutex2,mutex3;
int fd;
void * func_padre(void * n)
{
while(1)
{
pthread_mutex_lock(&mutex2);
printf("Scrivi messaggio: ");
fflush(stdout);
scanf("%[^\n]",(char *)addr_mem);
getchar();
pthread_mutex_unlock(&mutex3);
}
}
void * func_figlio(void * n)
{
while(1)
{
pthread_mutex_lock(&mutex3);
write(fd,addr_mem,4096);
lseek(fd,0,SEEK_SET);
memset(addr_mem,0,4096);
pthread_mutex_unlock(&mutex2);
}
}
int main(int argc, char*argv[])
{
if(argc<2)
{
printf("POCHI PARAMETRI\n");
fflush(stdout);
exit(-1);
}
int val=strtol(argv[2],0,10);
fd = open(argv[1],O_CREAT|O_RDWR,0666);
lseek(fd,0,SEEK_SET);//USELESS
///SHARED MEMORY
int id_mem;
id_mem = shmget(6543,4096,IPC_CREAT|0666);
addr_mem = shmat(id_mem,NULL,0);
/////////////////////
/// MUTEX
pthread_mutex_init(&mutex2,NULL);
pthread_mutex_init(&mutex3,NULL);
pthread_mutex_lock(&mutex3);
/////////////////////
pthread_t tid;
int i=0;
int pid;
pid = fork();
if(pid==0)
{
//CHILD
for(i=0; i<val; i++)
pthread_create(&tid,NULL,func_figlio,NULL);
while(1)
{
pthread_mutex_lock(&mutex3);
write(fd,addr_mem,4096);
memset(addr_mem,0,4096);
pthread_mutex_unlock(&mutex2);
}
}
else
{
//FATHER
for(i=0; i<val; i++)
pthread_create(&tid,NULL,func_padre,NULL);
while(1)
{
pthread_mutex_lock(&mutex2);
printf("Scrivi messaggio: ");
fflush(stdout);
scanf("%[^\n]",(char *)addr_mem);
getchar();
pthread_mutex_unlock(&mutex3);
}
}
}
Your problem is not a deadlock, it's just buggy code. A thread cannot unlock a mutex it did not lock. Your while loops all unlock mutexes they do not hold and never unlock the mutexes they do hold.
suggest:
have global variable that is cycled through a limited set of values, say: 0, 1, 0 ...
Use the mutex to stop other threads from progressing, I.E.
When a call (in thread) returns from locking the mutex,
then check
if the value in the global variable is for 'this' thread.
then
process the thread activities,
increment the global variable,
endif
endif
unlock the mutex
call nanosleep() to delay for a while to allow other threads to run
I need to send a signal to a child process 3 times.
The problem is that the child only receives the signal once and then transforms into a zombie.
The expected output would be:
I'm the child 11385 and i received SIGUSR1
I'm the child 11385 and i received SIGUSR1
I'm the child 11385 and i received SIGUSR1
But the real output is:
I'm the child 11385 and i received SIGUSR1
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
void my_handler()
{
printf("\n I'm the child %i and i received SIGUSR1\n", getpid());
}
int main (int argc, char **argv) {
int *array;
int N = 10;
int i;
pid_t pid1;
array=(int*)malloc(sizeof(int)*N);
signal(SIGUSR1,my_handler);
for (i = 0; i< N; i++)
{
pid1 = fork();
if(pid1 < 0)
{
exit(EXIT_FAILURE);
}
else if (pid1 > 0)
{
array[i]= pid1;
}
else
{
sleep(100);
exit(EXIT_SUCCESS);
}
}
i=0;
while(i<3) // I need to call the son 3 times
{
kill(array[1], SIGUSR1);
i++;
}
}
When the child receives the signal, it is probably waiting for the sleep to terminate. The first signal will interrupt the sleep even if the time hasn't expired, causing it to return with errno set to EINTR. If you want it to keep sleeping, you need to call sleep again.
your parent process exited without wait()ing for the child
The signals could be sent to fast, I added a short delay
i added more delays
the correct signature for a signal handler is void handler(int signum) This is crucial, because the handler is called with an argument, and the stack layout is different for signal handlers.
you should not call printf() from a signal handler, it is not async safe.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
char pidstr[10];
char massage[]=" I'm the child and i received SIGUSR1\n";
#define CNT 1
void my_handler(int signum)
{
write(0, massage, strlen(massage));
}
int main (int argc, char **argv) {
int i , err, status;
pid_t pid1;
int array[CNT];
signal(SIGUSR1, my_handler);
for (i = 0; i< CNT; i++) {
pid1 = fork();
if(pid1 < 0) { exit(EXIT_FAILURE); }
else if (pid1 > 0) {
printf("ChildPid=%d\n", pid1 );
array[i]= pid1;
}
else
{ // child
// signal(SIGUSR1, my_handler);
sprintf(pidstr,"[%d]", getpid() );
memcpy (massage,pidstr, strlen(pidstr));
sleep(10);
printf("Unslept\n");
sleep(10);
printf("Unslept\n");
sleep(10);
printf("Unslept\n");
exit(EXIT_SUCCESS);
}
}
sleep(10);
for (i=0; i<3; i++) {
err = kill(array[0], SIGUSR1);
printf("Err=%d:%d\n", err, (err) ? errno: 0 );
sleep(1);
}
while ( (pid1=wait( &status)) != -1){
printf("[Parent] Reaped %d\n", pid1);
}
return 0;
}
I'm supposed to write a program which creates 2 processes, connects between them with a pipe, and after a given time will end both processes and terminate.
one of the programs will write to the pipe, and the other will read from it and print it to STDOUT.
the reading process will be called first, then the pid will be passed to the second process so it will give SIGUSR1 signals to the first process, to tell it to read.
for some reason i never see the output in the terminal of the first process,
further more, it doesn't even print the line:"trying to exec1\n" which is where i call "execlp" for the process that prints.
here is the code for the 3 programs:
the main program:
#define STDERR 2
#define STDOUT 1
#define STDIN 0
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void alarmHandler(int sig);
void systemError();
char * intToString(int num , char number[4]);
static pid_t processId1, processId2;
int main(int argc, char ** argv){
pid_t pid1, pid2;
sigset_t block_mask1;
struct sigaction exitSig;
sigfillset(&block_mask1);
exitSig.sa_handler = alarmHandler;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
sigaction(SIGALRM, &exitSig, NULL);
if (argc < 2){
systemError();
} else {
int x = atoi(argv[1]);
alarm(x);
}
int fields[2];
if (pipe(fields)){
systemError();
}
if ((pid1 = fork()) == 0){
printf("trying to exec1\n");
close(STDIN);
dup(fields[0]);
close(fields[0]);
close(fields[1]);
if(execlp("./ex2_inp", "./ex2_inp", NULL)){
systemError();
}
} else {
processId1 = pid1;
if ((pid2 = fork()) == 0){
char number[350];
printf("trying to exec2\n");
close(STDOUT);
dup(fields[1]);
close(fields[0]);
close(fields[1]);
char * pidString = intToString(processId1, number);
if(execlp("./ex2_upd","./ex2_upd",pidString, NULL)){
systemError();
}
} else{
processId2 = pid2;
}
}
close(fields[0]);
close(fields[1]);
pause();
return 1;
}
/***********************
* handler for alarm signal
*************************/
void alarmHandler(int sig){
kill(processId2, SIGINT);
kill(processId1, SIGINT);
exit(1);
}
/***********************
* turn pid to string
*************************/
char * intToString(int num , char number[350]){
sprintf(number, "%d", num);
return number;
}
ex2_inp:
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
void printHandler(int sig);
int main(int argc, char * argv[]){
sigset_t block_mask1, block_mask2;
struct sigaction exitSig, print;
sigfillset(&block_mask1);
sigfillset(&block_mask2);
exitSig.sa_handler = exitHandler;
print.sa_handler = printHandler;
print.sa_mask = block_mask2;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
print.sa_flags = 0;
sigaction(SIGINT, &exitSig, NULL);
sigaction(SIGUSR1, &print, NULL);
pause();
return 1;
}
void exitHandler(int sig){
printf("exiting1!\n");
close(1);
exit(1);
}
void printHandler(int sig){
char * buffer[80];
read(1, buffer, 80);
printf("%s", buffer);
}
ex2_upd:
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
int main(int argc, char * argv[]){
sigset_t block_mask1;
struct sigaction exitSig;
sigfillset(&block_mask1);
exitSig.sa_handler = exitHandler;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
sigaction(SIGINT, &exitSig, NULL);
printf("2's message\n");
kill(atoi(argv[1]), SIGUSR1);
pause();
return 1;
}
void exitHandler(int sig){
printf("exiting2!\n");
close(0);
exit(1);
}
thanks
ex2_upd.c:
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
int main(int argc, char * argv[]){
sigset_t block_mask1;
struct sigaction exitSig;
sigfillset(&block_mask1);
exitSig.sa_handler = exitHandler;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
sigaction(SIGINT, &exitSig, NULL);
printf("2's message\n");
kill(atoi(argv[1]), SIGUSR1);
sleep(1); /* This was pause - causing ex2_inp read() to wait forever, since read() on pipe needs to either fill buffer or END_OF_FILE, unless we make the filedescriptor in the read-end non-blocking via fcntl() */
return 1;
}
void exitHandler(int sig){
printf("exiting2!\n");
close(0);
exit(1);
}
ex2_inp.c:
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
void printHandler(int sig);
int main(int argc, char * argv[]){
sigset_t block_mask1, block_mask2;
struct sigaction exitSig, print;
sigfillset(&block_mask1);
sigfillset(&block_mask2);
exitSig.sa_handler = exitHandler;
print.sa_handler = printHandler;
print.sa_mask = block_mask2;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
print.sa_flags = 0;
sigaction(SIGINT, &exitSig, NULL);
sigaction(SIGUSR1, &print, NULL);
pause();
return 1;
}
void exitHandler(int sig){
printf("exiting1!\n");
close(1);
exit(1);
}
void printHandler(int sig){
char buffer[80]; /* removed * */
read(0, buffer, 80); /* stdin is fd=0, not 1 */
printf("-> %s <-\n", buffer); /* added \n, forces new-line */
}
I'm currently being introduced to the concept of threading programs, and have been given an assignment to simulate a stockmarket using threads and semaphores. Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <pthread.h>
#define NUM_WRITERS 5
#define NUM_READERS 5
#define STOCKLIST_SIZE 10
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
sem_t stop_writers;
typedef struct
{ int readers;
int slots[STOCKLIST_SIZE];
} mem_structure;
int id[NUM_READERS + NUM_WRITERS];
mem_structure *stocklist;
pthread_t thr[NUM_WRITERS + NUM_READERS];
void init(){
sem_init(&stop_writers, 0, 1);
}
void cleanup(int signo) // clean up resources by pressing Ctrl-C
{ sem_destroy(&stop_writers);
printf("Closing...\n");
exit(0);
}
void write_stock(int n_writer)
{
int stock = (int)(rand()%STOCKLIST_SIZE);
int stock_value = 1 + (int)(100.0 * rand()/(RAND_MAX + 1.0));
stocklist->slots[stock] = stock_value;
fprintf(stderr, "Stock %d updated by BROKER %d to %d\n", stock, n_writer, stock_value);
}
void* writer(void* id){
int my_id = *((int*) id);
int i = my_id;
while (1)
{
pthread_mutex_lock(&mutex);
sem_wait(&stop_writers);
write_stock(i);
pthread_mutex_unlock(&mutex);
sem_post(&stop_writers);
sleep(1);
++i;
}
}
void read_stock(int pos, int n_reader){
fprintf(stderr, "Stock %d read by client %d = %d.\n", pos, n_reader, stocklist->slots[pos]);
}
void* reader(void* id){
int my_id = *((int*) id);
int i = my_id;
while (1)
{ sem_wait(&stop_writers);
read_stock((int)(rand()%STOCKLIST_SIZE), i);
sem_post(&stop_writers);
sleep(1 + (int) (3.0 * rand() / (RAND_MAX + 1.0)));
++i;
}
}
void monitor() // main process monitors the reception of Ctrl-C
{
struct sigaction act;
act.sa_handler = cleanup;
act.sa_flags = 0;
if ((sigemptyset(&act.sa_mask) == -1) ||
(sigaction(SIGINT, &act, NULL) == -1))
perror("Failed to set SIGINT to handle Ctrl-C");
while(1){
sleep(5);
printf("Still working...\n");
}
exit(0);
}
int main(void)
{ int i, j;
init();
for (i = 0; i < NUM_WRITERS; ++i){
id[i] = i;
pthread_create(&thr[i], NULL, writer, &id[i]);}
for (j = i; j < NUM_READERS; ++j){
id[j] = j;
pthread_create(&thr[j], NULL, reader, &id[j]);}
stocklist->readers = 0;
pthread_exit(NULL);
monitor();
return 0;
}
This is giving me a segmentation fault pretty much as soon as main() begins, with the creation of a thread... Since it's not code that I've created from root, I'm having trouble backtracing the error and fixing it - it would be great if there was someone who could take a look and maybe give me some hints
Thank you!
EDIT
Fixed the problem, thanks to your help :)
I initialized stocklist on init(),
void init(){
sem_init(&stop_writers, 0, 1);
stocklist = (mem_structure*)malloc(sizeof(mem_structure));
}
And changed the second cicle in main(),
for (j = i; j < NUM_READERS+NUM_WRITERS; ++j){
id[j] = j;
pthread_create(&thr[j], NULL, reader, &id[j]);}
Thanks
Here's what I did to track down the problem:
gcc -g program.c -lpthread
gdb a.out
run
Output:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7feeb70 (LWP 23060)]
0x08048834 in write_stock (n_writer=0) at program.c:44
44 stocklist->slots[stock] = stock_value;
Looks like the problem is here:
stocklist->slots[stock] = stock_value;
I have written the code below, and I want the following:
In every 5 secs the parent gets a random int and puts into into the shared mem, then sends a signal to its child.
The child calculates how many trams are needed to carry that amount of passengers (as you can see there are defs for TRAM_CAP etc) and then the child puts the new tram count into the shared mem.
Finally, after it is informed by a signal, the parent prints the count of passengers and trams.
My problem is that no signals are sent but I dont know why.
I searched and googled million times but nothing... The timer is working but nothing else (just the first "tram amount calculation")
Btw this is the second C code I have written in my life :S so I am a newbie.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "fcntl.h"
#include "errno.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "unistd.h"
#include <sys/time.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <math.h>
#define MEM_KEY 2003
#define INTERVAL 2
#define NEW_STAT SIGUSR1
#define NEW_TRAM_CNT SIGUSR2
#define MAX_PASSENGER 1000
#define TRAM_CAP 60
// "slots" in shared memory
#define PASS_CNT 0
#define TRAM_CNT 1
int get_pass_stat();
void handle_pass_stat_generation (int sig);
void handle_exit_func (int sig);
void set_pass_stat_generation();
void handle_new_tram_cnt_set(int sig);
void handle_new_stat_arrived(int sig);
void set_data(int which, int to);
int get_data(int which);
static pid_t ppid;
static pid_t chpid;
int main()
{
int shmid = shmget((key_t) MEM_KEY, sizeof(int) * 2, IPC_CREAT | 0666);
int* segptr = shmat(shmid, 0, 0);
segptr[PASS_CNT] = 0;
segptr[TRAM_CNT] = 0;
// seed for rand
srand((unsigned)time(NULL));
//
int pid=fork();
if(pid == 0) // child
{
signal(NEW_STAT, handle_new_stat_arrived);
while(1) sleep(30);
}else if(pid > 0) // parent
{
chpid = pid;
ppid = getpid();
signal(NEW_TRAM_CNT, handle_new_tram_cnt_set);
signal(SIGINT,handle_exit_func);
set_pass_stat_generation(pid);
while(1) sleep(30);
}else
{
perror("Fork error.");
exit(1);
};
return 0;
}
int get_pass_stat()
{
return rand() % MAX_PASSENGER + 1;
}
void handle_pass_stat_generation (int sig)
{
int st = get_pass_stat();
set_data(PASS_CNT, st);
kill( chpid, NEW_STAT );
printf("%i is the pass. cnt %i is the tram cnt. \n", st, get_data(TRAM_CNT));
// set_pass_stat_generation();
}
void handle_exit_func (int sig)
{
printf("\nBye Bye!!!\n");
exit(0);
}
void set_pass_stat_generation()
{
struct itimerval tval;
tval.it_interval.tv_sec = INTERVAL;
tval.it_interval.tv_usec = 0;
tval.it_value.tv_sec = INTERVAL; /* 5 seconds timer */
tval.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &tval,0);
signal(SIGALRM, handle_pass_stat_generation); /* set the Alarm signal capture */
}
void handle_new_stat_arrived(int sig)
{
int tram_count = get_data(TRAM_CNT);
int passenger_count = get_data(PASS_CNT);
if( (TRAM_CAP * tram_count < passenger_count) ||
(TRAM_CAP * (tram_count-1) > passenger_count) ||
(passenger_count == 0) )
{
int new_cnt = (int) ceil((double)passenger_count / (double)TRAM_CAP);
set_data(TRAM_CNT, new_cnt);
kill( ppid, NEW_TRAM_CNT );
}
signal(NEW_STAT, handle_new_stat_arrived);
}
void handle_new_tram_cnt_set(int sig)
{
signal(NEW_TRAM_CNT,handle_new_tram_cnt_set);
}
void set_data(int which, int to)
{
int shmid = shmget((key_t) MEM_KEY, 0, 0);
int* segptr = shmat(shmid, 0, 0);
segptr[which] = to;
}
int get_data(int which)
{
int shmid = shmget((key_t) MEM_KEY, 0, 0);
int* segptr = shmat(shmid, 0, 0);
return segptr[which];
}