Message sending and recieving not working using messagequeue - c

I am trying to send a message from child to parent (it has 2 children). But it returns error "Invalid Argument" when I run it in Xcode and when I run it in vim it is just pending and doing nothing. I want to send a message from 2nd child to Parent.
I have checked these, they are working finely :
Parent and child id matching
Arguments of msgrcv and msgsnd
fork and message queue creation
(I have added appropriate headers)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
void signalHandler(int signumber,siginfo_t* info,void* nonused){
printf("Signal with number %i has arrived\n",signumber);
switch (info->si_code){
case SI_USER:
printf("Process (PID number %i) sent the signal \n",info->si_pid); break;
case SI_QUEUE:
printf("It was sent by a sigqueue, sending process (PID %i)\n",info->si_pid);
default: printf("");
}
}
struct messg {
long mtype;
char mtext[1024];
};
int sendMsg (int mqueue){
const struct messg m = {5,"Test message"};
int status;
status = msgsnd(mqueue, &mqueue, strlen(m.mtext) + 1, IPC_NOWAIT);
if (status < 0){
perror("Message send error!");
}
return 0;
}
int receiveMsg(int mqueue){
struct messg m;
int status;
status = msgrcv(mqueue, &m, 1024 - sizeof(long), 5, 0);
if (status < 0){
printf("Errno : %d\n",status);
perror("Message recieve error!");
} else {
printf("Received msg : %s",m.mtext);
}
return 0;
}
int main(int argc, const char * argv[]) {
struct sigaction sigact;
sigact.sa_sigaction=signalHandler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags=SA_SIGINFO;
sigaction(SIGTERM,&sigact,NULL);
key_t key = ftok(argv[0],1);
int messg = msgget(key, 0600 | IPC_CREAT);
pid_t parent_co;
int pid_co_parent[2];
if (messg < 0){
perror("Message creation error!");
return 1;
}
pid_t child_nhp;
int pid_child_nhp[2];
char sz[250];
if(pipe(pid_co_parent) == -1){
perror("Pipe");
exit(0);
}
if(pipe(pid_co_parent) == -1){
perror("Pipe");
exit(0);
}
parent_co = fork();
if (parent_co == 0) {
sleep(3);
printf("(Police Lieutenant-colon) Child process : child_id : %d, parent_id : %d\n",getpid(),getppid());
kill(getppid(), SIGTERM);
read(pid_co_parent[0], sz, sizeof(sz));
printf("(Communication Officer) : %s\n" ,sz);
char answer[250];
strcpy(answer, "Yes, it is compulsory to wear the mask when you leave your flat!");
write(pid_co_parent[1], answer, strlen(answer) + 1);
close(pid_co_parent[0]);
return 0;
} else {
printf("(Communication Officer) Parent process_id : %d\n",getpid());
pause();
char ques[250];
strcpy(ques, "Is it compulsory to wear a mask in the shops?");
write(pid_co_parent[1], ques, strlen(ques) + 1);
close(pid_co_parent[1]);
read(pid_co_parent[0], sz, sizeof(sz));
printf("(Police Lieutenant-colon) : %s\n",sz);
close(pid_co_parent[0]);
child_nhp = fork();
if (child_nhp < 0){
perror("fork error for child nhp!");
exit(0);
}
if (child_nhp == 0) {
printf("(National Head Physician) child_id : %d, parent_id : %d\n",getpid(),getppid());
receiveMsg(messg);
return 0;
} else {
sendMsg(messg);
wait(NULL);
// parent process
}
fflush(NULL);
wait(NULL);
}
return 0;
}

Related

For some reason im getting wrong result using fork

The program creates a child proccess and the child does the proper work in order to see if its pid is even or odd
And for some reason even if the pid is even i get that it is odd , also the parent waits for child
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
pid_t pid, mypid, cpid;
int flag;
pid = getpid();
printf("Process %d creates new process\n\n", pid);
cpid = fork();
if (cpid == 0) {
cpid=getpid();
printf("\n----[%d] child\n", cpid);
if (cpid % 2 == 0) {
flag = 1;
} else {
flag = 0;
}
exit(0);
} else if (cpid != 0) {
wait(NULL);
mypid = getpid();
printf("\n[%d] parent of [%d]\n", mypid, cpid);
if (flag == 1) {
printf("\nThe child pid is even");
} else if(flag ==0) {
printf("\nThe child pid is odd");
} else {
printf("\nSomething went wrong");
}
} else {
perror("Fork failed");
}
return 0;
}

How to stop a process from being closed after certain signal is sent?

I need to create a program, which will create child process that will handle processes. In case of SIGXCPU called, child process should close, but when other signal is received, process shouldn't close, but display information. How could I change signals_handler function to stop closing my process?
I call signals from second terminal window.
void signals_handler(int signal) {
psignal(signal,"\nRecived signal");
printf("Signal number is: %d\n", signal);
return;
}
void sig_XCPU(int signal() {
signal(XCPU, sig_XCPU);
}
...
int main(void)
{
if(fork() == 0) {
print("PID: %d", getpid();
signal(SIGXCPU, sig_xcpu)
for(int = 1; i < 65; i++) {
if(i != 24) //SIGXCPU number
signal(i, signals_handler);
}
sleep(100);
return 0;
}
}
return 0;
}
You can test like this:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void signal_handle(int sig) {
switch (sig) {
case SIGXCPU: {
char st[] = "child recesive SIGXCPU, quit\n";
write(STDOUT_FILENO, st, sizeof(st));
exit(EXIT_SUCCESS);
break;
}
case SIGINT: {
char st[] = "child recesive SIGINT\n";
write(STDOUT_FILENO, st, sizeof(st));
break;
}
default: break;
}
return;
}
void set_signal() {
signal(SIGXCPU, signal_handle);
signal(SIGINT, signal_handle);
}
int main() {
pid_t pid = fork();
if (pid == 0) { // child
set_signal();
char st[] = "child set signal\n";
write(STDOUT_FILENO, st, sizeof(st));
for (;;)
;
}
// parent
sleep(3); // wait child set_signal
// test SIGINT
{
char st[] = "parent send SIGINT\n";
write(STDOUT_FILENO, st, sizeof(st));
kill(pid, SIGINT);
}
sleep(3);
// test SIGXCPU
{
char st[] = "parent send SIGXCPU\n";
write(STDOUT_FILENO, st, sizeof(st));
kill(pid, SIGXCPU);
}
wait(NULL);
return 0;
}

System Calls in C signals and fork

Hi I've this problem to solve with a functional program in C.
"Write a C program where a process F create a childprocess C.
The childprocess C waits the user to type the password, if is correct sends a signal SIGUSR1 to the father, if after 3 attempts the password is still incorrect it will send a SIGUSR2 signal to the father and terminate; if it receives from the father SIGUSR1 signal must stop viewing the "timeout" message.
His father after 30 seconds (if it has not received any signal from the child) must send the signal SIGUSR1 to the child and end with exit(1); if it receives the SIGUSR1 signal must end with exit(0); if it receives the signal SIGUSR2 must end with exit (2)."
I'm trying to solve it but I'm stuck. This is what I've done:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
void fatherprocess(int mysignal){
if (mysignal == SIGUSR1) {
printf("ACCESS GRANTED!\n");
exit(0);
}
if (mysignal == SIGUSR2){
printf("ACCESS DISCARDED! More than 3 tentatives!\n");
exit(2);
}
}
void childprocess(int mysignal){
if (mysignal == SIGUSR1) {
printf("TIMEOUT\n");
exit(1);
}
}
int main(int argc, char *argcv[]){
int fatherpid, childpid;
char enteredpassword[], password[] = "test";
int i =0;
unsigned int time_to_sleep = 30;
fatherpid = getpid();
childpid = fork();
if (childpid == 0) {
printf("Child Process waiting for a password\n");
while (1){
if (i < 3) {
printf("Enter Password: ");
scanf("%s", enteredpassword);
if (enteredpassword == password)
signal(SIGUSR1, fatherprocess);
} else {
signal(SIGUSR2, fatherprocess);
exit(1);
}
i++;
}
} else {
printf("Father Process\n");
while(time_to_sleep){
time_to_sleep = sleep(time_to_sleep);
signal(SIGUSR1, childprocess);
}
}
return 0;
}
I've edited my program in this way:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
void fatherprocess(int mysignal, int fatherpid){
if (mysignal == SIGUSR1) {
printf("ACCESS GRANTED!\n");
kill(fatherpid, SIGUSR1);
exit(0);
}
if (mysignal == SIGUSR2){
printf("ACCESS DISCARDED! More than 3 tentatives!\n");
kill(fatherpid, SIGUSR2);
exit(2);
}
}
void childprocess(int mysignal, int childpid){
if (mysignal == SIGUSR1) {
printf("TIMEOUT\n");
kill(childpid, SIGUSR1);
exit(1);
}
}
int main(int argc, char *argcv[]){
int fatherpid, childpid;
char enteredpassword[] = "test", password[] = "test";
int i =0;
unsigned int time_to_sleep = 30;
fatherpid = getpid();
childpid = fork();
if (childpid == 0) {
printf("Child Process waiting for a password\n");
while (1){
if (i < 3) {
printf("Enter Password: ");
scanf("%s", enteredpassword);
if (strcmp(enteredpassword, password) == 0)
fatherprocess(SIGUSR1, fatherpid);
} else {
fatherprocess(SIGUSR2, fatherpid);
exit(1);
}
i++;
}
} else {
printf("Father Process\n");
while(time_to_sleep){
time_to_sleep = sleep(time_to_sleep);
childprocess(SIGUSR1, childpid);
}
}
return 0;
}
Now it works perfectly but I don't know if I've respected the exercise text.
As was mentioned in the comments (by Jonathan Leffler), you need to use the kill() system call (to send the signals) and register a signal handler using a call like sigaction(). I have linked these two calls to online manual pages that provide additional information about them.
Here's some code that demonstrates how these can be used towards achieving your stated goal. You will still need to add/modify the code for things like the prompts you want and the acceptable input string. Please note that I'm not claiming this to be the best way to do it, only that it's an example of how it could be done (it compiled and worked for me):
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
static void get_password(char* buf, int maxbuf)
{
fgets(buf, maxbuf, stdin);
}
static int is_password_correct(char* buf)
{
return buf[0] == 'a';
}
volatile int got_signal = 0;
volatile int child_signal = 0;
static void parent_sig_handler(int signum)
{
if (!got_signal)
{
got_signal = signum;
printf("parent_sig_handler: got sig %d\n", signum);
}
}
static void child_sig_handler(int signum)
{
if (!child_signal)
{
child_signal = signum;
printf("child_sig_handler: got sig %d\n", signum);
}
}
int main()
{
struct sigaction act;
sigfillset(&act.sa_mask);
act.sa_handler = parent_sig_handler;
sigaction(SIGALRM, &act, NULL);
sigaction(SIGUSR1, &act, NULL);
sigaction(SIGUSR2, &act, NULL);
pid_t child_pid = fork();
if (child_pid == -1)
{
perror("error forking");
exit(3);
}
if (child_pid == 0)
{
printf("child running\n");
act.sa_handler = child_sig_handler;
sigaction(SIGUSR1, &act, NULL);
pid_t parent_pid = getppid();
for (int i = 0; i < 3; ++i)
{
char passwd[64];
passwd[0] = '\0';
get_password(passwd, sizeof(passwd));
if (is_password_correct(passwd))
{
kill(parent_pid, SIGUSR1);
exit(0);
}
}
kill(parent_pid, SIGUSR2);
exit(2);
}
printf("parent running\n");
alarm(30); /* sets parent up to receive a SIGALRM signal in 30 seconds */
sigset_t sigmask;
sigemptyset(&sigmask);
while (!got_signal)
{
sigsuspend(&sigmask);
}
switch (got_signal)
{
case SIGALRM:
kill(child_pid, SIGUSR1);
exit(1);
case SIGUSR1:
exit(0);
case SIGUSR2:
exit(2);
default:
exit(3);
}
exit(3);
}

process communication with signls

I am trying to write a C program which has some number of processes. One of them sends a random signal in the range SIGRTMIN and SIGRTMAX to all other processes but I want this signal will be ignored in main process.I used the global variable to have randomized signal to ignore with SIG_IGN. It looks It is not helping because the main stops with real-time signal when wants to ignore the first randomized signal.
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
volatile sig_atomic_t disarming_signal = 0;
void disarming_handler (int sig) {
disarming_signal = sig;
fprintf(stderr,"signal %d is handeled", disarming_signal);
}
int rand_range(int min_n, int max_n){
int rand_n = rand() % (max_n - min_n) + min_n;
return rand_n;
}
int sethandler (void (*f)(int), int sigNo) {
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = f;
if (-1==sigaction(sigNo, &act, NULL))
return -1;
return 0;
}
void sigchld_handler(int sig){
pid_t pid;
for(;;){
pid=waitpid(0, NULL, WNOHANG);
if(pid==0) return;
if(pid<=0) {
if(errno==ECHILD) return;
perror("waitpid:");
exit(EXIT_FAILURE);
}
}
}
void usage(){
fprintf(stderr,"USAGE: sappartherroryst n\n");
fprintf(stderr,"n - number of Therrorysts\n");
}
void therroryst_work(){
int s,k,t;
srand(getpid());
s = rand_range(SIGRTMIN, SIGRTMAX);
t = rand_range(10, 20);
k = t;
if(sethandler(disarming_handler, s)){
perror("Seting therroryst handeler");
exit(EXIT_FAILURE);
}
fprintf(stderr, "[%d] I am therroryst. My disarming signal is [%d]. I will wait [%d] Sec.\n", getpid(), s, t);
while(k>0) {
k=sleep(k);
if(disarming_signal == s){
fprintf(stderr, "I got signal [%d]\n.",disarming_signal);
return ;
}
}
fprintf(stderr, "[%d] KABOOM\n",getpid());
exit(EXIT_SUCCESS);
}
void create_therrorysts(int n){
while(n-->0){
switch(fork()) {
case 0:
therroryst_work();
exit(EXIT_SUCCESS);
case -1:
perror("Fork():");
exit(EXIT_FAILURE);
}
}
}
void sapper_work(){
int sig_dis, i;
struct timespec t, tn = {1,0};
fprintf(stderr,"[%d] I am sapper.\n", getpid());
for(i=0;i<10;i++){
for(t=tn;nanosleep(&t,&t););
sig_dis = rand_range(SIGRTMIN, SIGRTMAX);
if(kill(0, sig_dis)<0){
perror("Disarming_send\n");
exit(EXIT_FAILURE);
}
fprintf(stderr,"I sended signal [%d].\n",sig_dis);
disarming_signal = sig_dis;
}
fprintf(stderr, "end of sending");
exit(EXIT_SUCCESS);
}
void create_sapper(){
switch(fork()) {
case 0:
sapper_work();
exit(EXIT_SUCCESS);
case -1:
perror("Fork():");
exit(EXIT_FAILURE);
}
}
int main(int argc, char** argv){
int n;
pid_t pid;
if(argc != 2){
usage();
return EXIT_FAILURE;
}
n = atoi(argv[1]);
if(n <= 0){
usage();
return EXIT_FAILURE;
}
if(sethandler(sigchld_handler, SIGCHLD)) {
perror("Seting parent SIGCHLD:");
exit(EXIT_FAILURE);
}
create_therrorysts(n);
create_sapper();
sleep(5);
for(;;) {
if(sethandler(SIG_IGN, disarming_signal)){
perror("Seting parent disarming111");
exit(EXIT_FAILURE);
}
}
for(;;){
pid=wait(NULL);
if(pid<0)
switch (errno){
case ECHILD:
return EXIT_SUCCESS;
case EINTR:
continue;
default:
perror("wait:");
exit(EXIT_FAILURE);
}
}
return EXIT_SUCCESS;
}
You have sleep(5) after the create_sapper and before sethandler(IGN). That means it's very likely that the signal is sent before your main process has ignored it.
EDIT: Adding comment from Jonathan Leffler into this answer as it is equally (or even more) important:
There's also a problem with setting the signal handler even if you put the sleep() after that loop - the parent doesn't get to see what the child chooses as disarming_signal.

execlp redirect stdin in c

Question is simple
I've searched around but I couldn't find the solution
char *data1;
char *data2;
pid_t pid = fork();
int stat;
if (pid == 0){
execlp("Program B");
} else {
wait(&stat);
if (WIFEXITED(stat))
printf("%d\n", WEXITSTATUS(stat));
}
the thing is I need to send data1 and data2 to Program B as stdin
but I couldn't find the solution
how can I deal with this?
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
char *data1 = "First message.\n";
char *data2 = "What the rest of the world has been waiting for.\n";
pid_t pid;
int p[2];
if (pipe(p) < 0)
perror("pipe() failed");
else if ((pid = fork()) < 0)
perror("fork() failed");
else if (pid == 0)
{
dup2(p[0], STDIN_FILENO);
close(p[0]);
close(p[1]);
execlp("cat", "cat", (char *)0);
perror("execlp() failed");
}
else
{
close(p[0]);
write(p[1], data1, strlen(data1));
write(p[1], data2, strlen(data2));
close(p[1]);
int status;
int corpse = wait(&status);
if (WIFEXITED(status))
printf("%d exited with status %d\n", corpse, WEXITSTATUS(status));
}
return 0;
}
Note how many closes are necessary.
Building a pipe to stdin is the way to go,
Like
char *data1;
char *data2;
int stat;
pid_t pid;
if( pipe(pfd) < 0 ) {
perror("pipe");
return 1;
}
pid = fork();
if (pid == 0)
{
// Close the writing end of the pipe
close(pfd[1]);
execlp("Program B");
}
else if(pid==-1)
{
perror("fork");
}
else
{
// Write to the pipe.
if (write(pfd[1], "This is my data \n", 16) != 16)
perror("write");
close(pfd[1]);
wait(&stat);
if (WIFEXITED(stat))
printf("%d\n", WEXITSTATUS(stat));
}
You can provide data as argument list to the new process.
Syntax:- int execlp(const char *path, const char *arg0, ..., NULL);
So your call can look something like this
// convert the input data into string format i.e data1 and data2 should be strings
execlp("Program B","Program B",data1,data2,NULL);
In program B use appropriately to convert it into whatever type you want to.

Resources