Interprocess communication with messages under linux - linux

So basically, I have 5 processes, which are communicating like this - the 5th process sends its PID to the 4th, the 4th sends its own PID and the 5th's PID to the 3rd process and so on, and in the end the 1st process shows the PIDs of all the other processes. I've done the communication via pipes communication:
#include <sys/unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void){
int pid,pid1,pid2,pid3;
int fd[2],fd1[2],fd2[2],fd3[2];
pipe(fd);
if( (pid = fork()) != 0 ) { //parent
int temp[5];
close(fd[1]);
read(fd[0],&temp,sizeof(temp));
temp[0]=getpid();
int i;
for(i=0;i<5;i++) {
printf("%d\n",temp[i]);
}
wait(); //wait for the child to complete
}
else { //child
pipe(fd1);
if( (pid1 = fork() ) != 0 ) { //parent
int temp[5];
close(fd1[1]);
read(fd1[0],&temp,sizeof(temp));
temp[1]= getpid();
close(fd[0]);
write(fd[1],&temp,sizeof(temp));
wait();
}
else { //child
pipe(fd2);
if( (pid2 = fork() ) != 0 ) { //parent
int temp[5];
close(fd2[1]);
read(fd2[0],&temp,sizeof(temp));
temp[2]= getpid();
close(fd1[0]);
write(fd1[1],&temp,sizeof(temp));
wait();
}
else { //child
pipe(fd3);
if( (pid3 = fork() ) != 0 ) { //parent
int temp[5];
close(fd3[1]);
read(fd3[0],&temp,sizeof(temp));
temp[3]= getpid();
close(fd2[0]);
write(fd2[1],&temp,sizeof(temp));
wait();
}
else { //child
int temp[5];
temp[4] = getpid();
close(fd3[0]);
write(fd3[1],&temp,sizeof(temp));
}
}
}
}
return 0;
}
But I have hard time doing the communication via messages. I can provide more information if needed. Any suggestion will be greatly appreciated. Thank you in advance for your time.

Related

Does the CHILD_SUBREAPER bit persist across fork()?

When a process sets the child subreaper bit with prctl(PR_SET_CHILD_SUBREAPER, 1) (documented here), does it need to use prctl(PR_SET_CHILD_SUBREAPER, 0) to clear it after a fork?
No, the child subreaper bit does not persist across forks.
The relevant Linux kernel code is in copy_signal() in kernel/fork.c: the signal struct is initialized to all zeros, and the is_child_subreaper bit is never set.
However, has_child_subreaper is set:
sig->has_child_subreaper = current->signal->has_child_subreaper ||
current->signal->is_child_subreaper;
This test program demonstrates the behavior:
#include <stdio.h>
#include <stdlib.h>
#include <sys/prctl.h>
int main(int argc, char** argv) {
int pid;
int i;
prctl(PR_SET_CHILD_SUBREAPER, 1);
prctl(PR_GET_CHILD_SUBREAPER, &i);
printf("Before fork: %d\n", i);
pid = fork();
if (pid < 0) {
return 1;
} else if (pid == 0) {
prctl(PR_GET_CHILD_SUBREAPER, &i);
printf("In child: %d\n", i);
return 0;
}
return 0;
}
Outputs:
Before fork: 1
In child: 0

Cygwin: interrupting blocking read

I've written the program which spawns a thread that reads in a loop from stdin in a blocking fashion. I want to make the thread return from blocked read immediately. I've registered my signal handler (with sigaction and without SA_RESTART flag) in the reading thread, send it a signal and expect read to exit with EINTR error. But it doesn't happen. Is it issue or limitation of Cygwin or am I doing something wrong?
Here is the code:
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
pthread_t thread;
volatile int run = 0;
void root_handler(int signum)
{
printf("%s ENTER (thread is %x)\n", __func__, pthread_self());
run = 0;
}
void* thr_func(void*arg)
{ int res;
char buffer[256];
printf("%s ENTER (thread is %x)\n", __func__, pthread_self());
struct sigaction act;
memset (&act, 0, sizeof(act));
act.sa_sigaction = &root_handler;
//act.sa_flags = SA_RESTART;
if (sigaction(SIGUSR1, &act, NULL) < 0) {
perror ("sigaction error");
return 1;
}
while(run)
{
res = read(0,buffer, sizeof(buffer));
if(res == -1)
{
if(errno == EINTR)
{
puts("read was interrupted by signal");
}
}
else
{
printf("got: %s", buffer);
}
}
printf("%s LEAVE (thread is %x)\n", __func__, pthread_self());
}
int main() {
run = 1;
printf("root thread: %x\n", pthread_self());
pthread_create(&thread, NULL, &thr_func, NULL);
printf("thread %x started\n", thread);
sleep(4);
pthread_kill(thread, SIGUSR1 );
//raise(SIGUSR1);
pthread_join(thread, NULL);
return 0;
}
I'm using Cygwin (1.7.32(0.274/5/3)).
I've just tried to do the same on Ubuntu and it works (I needed to include signal.h, though, even though in Cygwin it compiled as it is). It seems to be peculiarity of Cygwin's implementation.

pclose() returns SIGPIPE intermittently

When the following C program is executed, and SIGUSR1 is sent to the running process repeatedly, the pclose() call will sometimes return 13. 13 corresponds to SIGPIPE on my system.
Why does this happen?
I am using while true; do kill -SIGUSR1 <process-id>; done to send SIGUSR1 to the program. The program is executed on Ubuntu 14.04.
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
void handler(int i) {}
void* task(void*)
{
FILE *s;
char b [BUFSIZ];
while (1) {
if ((s = popen("echo hello", "r")) == NULL) {
printf("popen() failed\n");
}
while (fgets(b, BUFSIZ, s) != NULL) ;
if (int r = pclose(s)) {
printf("pclose() failed (%d)\n", r);
}
}
return 0;
}
int main(int argc, char **argv)
{
struct sigaction action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
sigaction(SIGUSR1, &action, NULL);
pthread_t tid;
pthread_create(&tid, 0, task, NULL);
pthread_join(tid, NULL);
}
This happens when fgets gets interrupted by the signal. The program doesn't read the pipe to the end and closes it. The other program then SIGPIPEs.
The correct pipe reading operation is:
do {
while (fgets(b, BUFSIZ, s) != NULL) ;
} while (errno == EINTR);

Segmentation Fault when using Threads and Semaphores, Mac Vs Linux

My problem deals with a segmentation fault that I get when I run this program on a linux machine versus my own mac computer. This program runs how I believe it should on my own mac computer, yet when I try to run it on my school's linux computers, I get a segmentation fault that doesn't appear on my mac computer. I'll give a brief background on the assignment and then go over the problem in more detail.
So I have this program which basically simulates baboons crossing a ravine with a single rope. Only one baboon can cross at a time and there are certain restraints on the number of baboons that can cross at a time, as well as how many baboons can cross from one direction before baboons from the other direction are allowed to cross. The implementation of the code.
I have searched for segmentation fault questions already here on stackoverflow, yet most of them deal with multiple processes whereas I am merely using different threads. The segmentation fault ends up coming from waiting on a semaphore that doesn't exist, yet when I checked to see whether it was initialized, it was successfully initialized. Again, this program works on my mac but then doesn't work when I try to run it on my Mac. Any help at all understanding why it can't run on the linux machines but can run on the mac. If any more information is needed, I would be happy to provide it. I did error check at one point but that code was deleted off the school computers. My error checking, as far as I remember, didn't show any errors.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include <pthread.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h> //for mode flags, if needed for future use
#define ATOB_COUNT 20
#define BTOA_COUNT 20
#define RANDOM_SEED 2123
//semaphore names
#define MUTEX_SEM "/mutex"
#define TOB_SEM "/toB"
#define TOA_SEM "/toA"
//define methods here if needed
void *toAThread(void *threadId);
void *toBThread(void *threadId);
void my_sleep(int limit);
void sem_open_errorCheck(char *name, unsigned int startingValue, sem_t *result);
//defining semaphores and shared variables
sem_t *mutex, *toB, *toA;
int xingCount = 0;
int xedCount = 0;
int toBWaitCount = 0;
int toAWaitCount = 0;
enum xingDirectionTypes {
none,
aToB,
bToA
};
enum xingDirectionTypes xingDirection = none;
char orderLeaving[100];
struct threadInfo {
int threadId;
};
struct threadInfo atobIDs[ATOB_COUNT];
struct threadInfo btoaIDs[BTOA_COUNT];
int main(void) {
pthread_t atobPTHREADS[ATOB_COUNT];
pthread_t btoaPTHREADS[BTOA_COUNT];
pthread_attr_t attr;
void *status;
srandom(RANDOM_SEED);
//call helper method which creates semaphore and errorchecks
sem_open_errorCheck(MUTEX_SEM, (unsigned int)1, mutex);
sem_open_errorCheck(TOA_SEM, (unsigned int)0, toA);
sem_open_errorCheck(TOB_SEM, (unsigned int)0, toB);
//Creating a set of attributes to send to the threads
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
//spawn toB baboons
int counter;
for (counter = 0; counter < BTOA_COUNT; counter++) {
atobIDs[counter].threadId = counter;
int result;
if ((result = pthread_create(&atobPTHREADS[counter], &attr, toBThread, (void*) &atobIDs[counter])) == -1) {
perror("Thread Creation Error: atob baboon");
exit(EXIT_FAILURE);
}
}
//spawn toA baboons
for (counter = 0; counter < ATOB_COUNT; counter++) {
btoaIDs[counter].threadId = counter + 20;
int result;
if ((result = pthread_create(&btoaPTHREADS[counter], &attr, toAThread, (void*) &btoaIDs[counter])) == -1) {
perror("Thread Creation Error: btoa baboon");
exit(EXIT_FAILURE);
}
}
//Wait for all the threads to finish
for(counter = 0; counter < ATOB_COUNT; counter++)
{
int result = pthread_join(atobPTHREADS[counter], &status);
if(result == -1)
{
perror("Thread Join: AtoB");
exit(EXIT_FAILURE);
}
}
for(counter = 0; counter < BTOA_COUNT; counter++)
{
int result = pthread_join(btoaPTHREADS[counter], &status);
if(result == -1)
{
perror("Thread Join: BtoA");
exit(EXIT_FAILURE);
}
}
printf("The order leaving %s", orderLeaving);
exit(EXIT_SUCCESS);
}
void *toBThread(void *threadId) {
struct threadInfo *info;
info = (struct threadInfo *)threadId;
int id = info->threadId;
my_sleep(100); //simulate being idle for 1-100ms
//for order checking
char *baboonOrder;
baboonOrder = "B ";
strcat(orderLeaving, baboonOrder);
sem_wait(mutex);
if ((xingDirection == aToB || xingDirection == none) && xingCount < 5 && (xedCount + xingCount) < 10) { //there is an extra parenthesis here in the solutions
xingDirection = aToB;
xingCount++;
printf("AtoB baboon (thread %d) got on the rope\n", id);
sem_post(mutex);
}
else {
toBWaitCount++;
sem_post(mutex);
sem_wait(toB);
toBWaitCount--;
xingCount++;
xingDirection = aToB;
printf("AtoB baboon (thread %d) got on the rope\n", id);
sem_post(mutex);
}
//CROSSING
sem_wait(mutex);
printf("AtoB baboon (thread %d) got off the rope\n", id);
xedCount++;
xingCount--;
if (toBWaitCount != 0 && (((xedCount+xingCount)<10) || ((xedCount+xingCount) >= 10 && toAWaitCount == 0))) {
sem_post(toB);
}
else {
if (xingCount == 0 && toAWaitCount != 0 && (toBWaitCount == 0 || (xedCount + xingCount)>=10)) {
xingDirection = bToA;
xedCount = 0;
sem_post(toA);
}
else {
if (xingCount == 0 && toBWaitCount == 0 && toAWaitCount == 0) {
xingDirection = none;
xedCount = 0;
sem_post(mutex);
}
else {
sem_post(mutex);
}
}
}
}
/*
baboons going from side a to side b
*/
void *toAThread(void *threadId) {
struct threadInfo *info;
info = (struct threadInfo *)threadId;
int id = info->threadId;
my_sleep(100);
//for order checking
char *baboonOrder;
baboonOrder = "A ";
strcat(orderLeaving, baboonOrder);
sem_wait(mutex);
if ((xingDirection == bToA || xingDirection == none) && xingCount < 5 && (xedCount + xingCount) < 10) { //there is an extra parenthesis here in the solutions
xingDirection = bToA;
xingCount++;
printf("BtoA baboon (thread %d) got on the rope\n", id);
sem_post(mutex);
}
else {
toAWaitCount++;
sem_post(mutex);
sem_wait(toA);
toAWaitCount--;
xingCount++;
xingDirection = bToA;
printf("BtoA baboon (thread %d) got on the rope\n", id);
sem_post(mutex);
}
//CROSSING
sem_wait(mutex);
printf("BtoA baboon (thread %d) got off the rope\n", id);
xedCount++;
xingCount--;
if (toAWaitCount != 0 && (((xedCount+xingCount)<10) || ((xedCount+xingCount) >= 10 && toBWaitCount == 0))) {
sem_post(toA);
}
else {
if (xingCount == 0 && toBWaitCount != 0 && (toAWaitCount == 0 || (xedCount + xingCount)>=10)) {
xingDirection = aToB;
xedCount = 0;
sem_post(toB);
}
else {
if (xingCount == 0 && toAWaitCount == 0 && toBWaitCount == 0) {
xingDirection = none;
xedCount = 0;
sem_post(mutex);
}
else {
sem_post(mutex);
}
}
}
}
//taken with permission from readers/writers problem
//Puts the calling thread to sleep to simulate both random start times and random workloads
void my_sleep(int limit) {
struct timespec time_ns;
int duration = random() % limit + 1;
time_ns.tv_sec = 0;
time_ns.tv_nsec = duration * 1000000;
int result = nanosleep(&time_ns, NULL);
if (result != 0)
{
perror("Nanosleep");
exit(EXIT_FAILURE);
}
}
void sem_open_errorCheck(char *name, unsigned int startingValue, sem_t *result) {
sem_unlink(name);
result = sem_open(name, O_CREAT, 0600, startingValue);
if (result == -1) {
perror("sem_open error: semaphore failed to open correctly");
exit(EXIT_FAILURE);
}
}
How to debug stuff like this
The best way to debug this is to run it using the gdb debugger. Like this:
gdb my-monkey-program
(gdb) run
Program received signal SIGSEGV, Segmentation fault.
(gdb) info threads
(gdb) bt
Another excellent idea is to run it with valgrind:
valgrind ./my-monkey-program
which will tell you about invalid memory accesses and all sorts of things.
Your specific problem
gdb reports that the call stack is:
#0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:45
#1 0x0000000000400e8d in toAThread (threadId=0x602160) at test.c:190
#2 0x00007ffff7bc4e9a in start_thread (arg=0x7fffed7e9700) at pthread_create.c:308
#3 0x00007ffff78f1cbd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
#4 0x0000000000000000 in ?? ()
Here are the line numbers from my compile:
187 baboonOrder = "A ";
188 strcat(orderLeaving, baboonOrder);
189
190 sem_wait(mutex);
This is because mutex is NULL.
Why it breaks
You're never actually assigning to the mutex variable. You're passing a pointer into sem_open_errorCheck, but what you really need to pass is a pointer-to-a-pointer. Presumably the same applies to toA and toB.
It's just luck that it worked on the Mac!

SIGUSR1 not received

This is my first Program....ctrlcsignal.c
enter code here
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
void signal_handler(int sigNo)
{
//if Ctrl+c signal
if(sigNo==SIGINT){
printf("value of SIGINT:-%d\t",SIGINT);
printf("received SIGINT\n");
}
// if some other signal , but this part wont get executed
// as the signal_handler function is registered with SIGINT only
else
{
printf("Some other signal found");
printf("value of other signal:-%d",sigNo);
}
}
int main(void)
{
//registering the signal handler function with a signal
kill(19574,SIGUSR1);
if(signal(SIGINT,signal_handler)==SIG_ERR)
{
printf("\n can't catch SIGINT\n");
}
while(1) //infinite loop
sleep(1); // 1s ,so that the CPU is not busy
return 0;
}
and this my second program....userdefinedsignals.c
enter code here
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void signal_handler(int sigNo)
{
printf("function entered...");
// check for userdefined Signal SIGUSR1
if (sigNo == SIGUSR1)
{
printf("received SIGUSR1 with value :- %d",SIGUSR1);
}
//checking for KILL Signal
else if (sigNo == SIGKILL)
{
printf("received SIGKILL with value :- %d",SIGKILL);
}
//checking for STOP Signal
else if (sigNo == SIGSTOP)
{
printf("received SIGSTOP with value :- %d",SIGSTOP);
}
// if some other signal , but this part wont get executed
// as the signal_handler function is registered with SIGINT only
else
{
printf("Some other signal found");
printf("value of other signal:-%d",sigNo);
}
}
int main(void)
{
int pid_t;
printf("process id is %d",getpid());
//registering the signal handler function with a signal
if(signal(SIGUSR1,signal_handler) == SIG_ERR)
{
printf("\n can't catch SIGSIGUSR1\n");
}
if(signal(SIGKILL,signal_handler)==SIG_ERR)
{
printf("\n can't catch SIGKILL\n");
}
if(signal(SIGSTOP,signal_handler)==SIG_ERR)
{
printf("\n can't catch SIGSTOP\n");
}
while(1) //infinite loop
sleep(1); // 1s ,so that the CPU is not busy
return 0;
}
I get the pid of the second process ... suppose xxxx
then i use the following command...
enter code here
kill -USR1 xxxx
but it shows nothing ....
also then i tried by calling the following function int the first program...but no use..
enter code herekill(xxxx,SIGUSR1);
HELP ME..!!!!
Works here.
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdarg.h> /* vsnprintf() */
#include <signal.h> /* signal */
void myprintf(FILE *fp, char *fmt, ...)
{
char buff[512];
int rc,fd;
va_list argh;
va_start (argh, fmt);
rc = vsnprintf(buff, sizeof buff, fmt, argh);
if (rc < 0 || rc >= sizeof buff) {
rc = sprintf(buff, "Argh!: %d:\n", rc);
}
if (!fp) fp = stderr;
fd = fileno(fp);
if (fd < 0) return;
if (rc > 0) write(fd, buff, rc);
return;
}
void signal_handler(int sigNo)
{
switch (sigNo ) {
case SIGUSR1:
myprintf(NULL, "received SIGUSR1 with value :- %d\n", SIGUSR1);
break;
case SIGKILL:
myprintf(NULL, "received SIGKILL with value :- %d\n", SIGKILL);
break;
case SIGSTOP:
myprintf(NULL, "received SIGSTOP with value :- %d\n", SIGSTOP);
break;
default:
myprintf(NULL, "Some other signal occured: %d\n", sigNo);
break;
}
return;
}
int main(void)
{
pid_t mypid;
mypid = getpid();
printf("process id is %d\n", (int) mypid);
if(signal(SIGUSR1,signal_handler) == SIG_ERR)
{ printf("\n can't catch SIGSIGUSR1\n"); }
if(signal(SIGKILL,signal_handler)==SIG_ERR)
{ printf("\n can't catch SIGKILL\n"); }
if(signal(SIGSTOP,signal_handler)==SIG_ERR)
{ printf("\n can't catch SIGSTOP\n"); }
if(signal(SIGCONT,signal_handler)==SIG_ERR)
{ printf("\n can't catch SIGCONT\n"); }
while(1) {
sleep(1);
}
return 0;
}
You're catching the signal all right, but not seeing the message because you don't terminate lines properly, and the standard output stream on your system is line buffered (assuming your program runs in a terminal).
Standard C defines three levels of buffering for output streams:
unbuffered, where output is transmitted immediately
line buffered, where output is transmitted when a newline character is encountered
fully buffered, where output is transmitted when an internal buffer fills
(This is a simplification - see a C reference or the Standard for details).
Consider:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
printf("Hello");
pause();
}
This produces no output in a terminal. Fix it by terminating the line:
printf("Hello\n");
This will produce the expected output in a terminal.
If stdout is not connected to a terminal - for example, you redirect to a file - then the stream becomes fully buffered. This:
./a.out > foo
Ctrl-C
cat foo
produces no output, even with the newline character added. Here you need an explicit flush to transmit the output before the buffer is full.
#include <stdio.h>
#include <unistd.h>
int main(void)
{
printf("Hello\n");
fflush(stdout);
pause();
}
This produces output even when redirected to a file.

Resources