I've already asked a similar question a few days ago. Basically I have to make a daemon-client communicate via named tubes. The client part is done and sends messages correctly, but the daemon part seems to not be receiving anything... Here's the code:
void makeDaemon(){
int i,fd0,fd1,fd2;
pid_t pid;
struct sigaction sa;
struct rlimit rl;
umask(0);
if(getrlimit(RLIMIT_NOFILE, &rl)<0) exit(EXIT_FAILURE);
if((pid=fork())<0) exit(EXIT_FAILURE);
if(pid>0) exit(EXIT_SUCCESS);
setsid();
sa.sa_handler=SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
if(sigaction(SIGHUP, &sa, NULL)<0) exit(EXIT_FAILURE);
if((pid=fork())<0) exit(EXIT_FAILURE);
if(pid>0) exit(EXIT_SUCCESS);
//if(chdir("/")<0) exit(EXIT_FAILURE);
if(rl.rlim_max=RLIM_INFINITY) rl.rlim_max=1024;
for(i=0;i< rl.rlim_max; i++) close(i);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
//sigaction(SIGUSR1,&sac,NULL);
}
int main(){
makeDaemon();
char* path="./run/pipes/saturnd-request-pipe";
char* path2="./run/pipes/saturnd-reply-pipe";
//Creation d'un pipe au cas où il n'existe pas
//mkfireply_pipe(path,0666);
int timeout=5000;
struct pollfd pf[1];
int request_pipe;
while(1){
request_pipe=open(path,O_RDONLY);
if(request_pipe==-1){
perror("Erreur d'ouverture du pipe");
exit(EXIT_FAILURE);
}
pf[0].fd=request_pipe;
pf[0].events=POLLIN;
int p=poll(pf,1,timeout);
if(pf[0].revents & POLLIN){
char tmp1[2];
ssize_t s=read(request_pipe,tmp1,2);
if(s==-1) exit(EXIT_FAILURE);
printf("%s\n",tmp1);
int i=1;
}else{
printf("Timed out\n");
break;
}
return 0;
}
}
My question is, should I maybe make a handler containing this while loop so that the daemon can receive a signal? As of right now, it just times out and dies. We cannot use sockets, and everything is done via these two names pipes. Any suggestion would be appreciated. Thanks!
Related
So, I've made a function in C that "daemonizes" a program, but when I do so, any code I want the daemon to execute, is not executed... even though the daemon is up and running in the background.
void makeDaemon(){
int i,fd0,fd1,fd2;
pid_t pid;
struct sigaction sa;
struct rlimit rl;
umask(0);
if(getrlimit(RLIMIT_NOFILE, &rl)<0) exit(EXIT_FAILURE);
if((pid=fork())<0) exit(EXIT_FAILURE);
if(pid>0) exit(EXIT_SUCCESS);
setsid();
sa.sa_handler=SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
if(sigaction(SIGHUP, &sa, NULL)<0) exit(EXIT_FAILURE);
if((pid=fork())<0) exit(EXIT_FAILURE);
if(pid>0) exit(EXIT_SUCCESS);
if(chdir("/")<0) exit(EXIT_FAILURE);
if(rl.rlim_max=RLIM_INFINITY) rl.rlim_max=1024;
for(i=0;i< rl.rlim_max; i++) close(i);
fd0=open("/dev/null",O_RDWR);
fd1=dup(0);
fd2=dup(0);
if(fd0!=0 || fd1!=1 || fd2!=2) exit(EXIT_FAILURE);
}
This is the "daemonizing" function, and this is an other program that I want to daemonize but it just doesnt do what it should...
int main(int argc, char ** argv){
makeDaemon();
char* path="./run/pipes/saturnd-request-pipe";
char* path2="./run/pipes/saturnd-reply-pipe";
//Creation d'un pipe au cas où il n'existe pas
//mkfireply_pipe(path,0666);
//Ouverture du pipe
int request_pipe;
request_pipe=open(path,O_RDONLY);
if(request_pipe==-1){
perror("Erreur d'ouverture du pipe");
return -1;
}
int reply_pipe;
reply_pipe=open(path2,O_WRONLY);
if(reply_pipe==-1){
perror("Erreur d'ouverture du pipe");
return -1;
}
char tmp1[2];
read(request_pipe,tmp1,2);
printf("%s",tmp1);
}
If someone has any advice on how to connect the two, I'd greatly appreciate it.
I am trying to have a process read both from a named pipe and some unnamed pipes. First I have a main process that creates a child process and then initializes a named pipe that waits for data from the terminal to send to the named pipe:
int main(){
signal(SIGINT, sigint);
if(fork()==0){
newProcess();
exit(0);
}
unlink(PIPE_NAME);
printf("Creating named pipe.\n");
if ((mkfifo(PIPE_NAME, O_CREAT|O_EXCL|0600)<0) && (errno!= EEXIST)) {
perror("Cannot create pipe: ");
exit(0);
}
printf("Named pipe created.\n");
int named_pipe_fd;
printf("Opening named pipe.\n");
if ((named_pipe_fd = open(PIPE_NAME, O_WRONLY)) < 0) {
perror("Cannot open pipe for writing: ");
exit(0);
}
printf("Named pipe open.\n");
char toSend[512];
//Sends data via the NAMED pipe to our child process
while(1){
scanf("%[^\n]%*c", toSend);
printf("[RaceSimulator] Sending (%s)\n",toSend);
write(named_pipe_fd, toSend, sizeof(toSend));
}
return 0;
}
The child process opens the named pipe into reading mode and creates an array full of file descriptors that wait for information to come their way. For now I have the unnamed pipes not created yet and so, their value in the array is -1:
void newProcess(){
//Initialize the pipes
for(int i=0;i<MAX;i++){
pipes[i]=-1;
}
//OPEN NAMED PIPE FOR READING
int fd;
if ((fd= open(PIPE_NAME, O_RDONLY)) < 0) {
perror("Cannot open pipe for reading: ");
exit(0);
}
pipes[0]=fd;
char received[512];
//Loop that waits for data to appear in the pipes
while(1){
fd_set read_set;
FD_ZERO(&read_set);
for (int channel=0;channel<MAX;channel++) {
FD_SET(pipes[channel], &read_set);
}
if (select(pipes[MAX-1]+1, &read_set, NULL, NULL, NULL) > 0 ) {
if (FD_ISSET(pipes[0], &read_set)) {
read(pipes[0],received,sizeof(received));
printf("[Named pipe] Received %s.\n",received);
}
//Unamed pipes are still not created!
for (int channel=1;channel<MAX;channel++) {
if (FD_ISSET(pipes[channel], &read_set)) {
read(pipes[channel],received,sizeof(received));
printf("[Unamed pipe] Received %s.\n",received);
}
}
}
}
}
The problem, is that when I write on the terminal, the terminal writes back only the printf of the main process. This means that nothing is being sent to the other side of the named pipe but I do not understand why. Here is the whole code (NOTE: this is a snippet, for legal reasons I cannot send the original code, also I know I have too many includes in this snippet :P):
#define PIPE_NAME "pipe"
#define MAX 5
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <sys/stat.h>
int pipes[MAX];
void clean(){
unlink(PIPE_NAME);
}
void sigint(int signum){
clean();
exit(0);
}
void newProcess(){
//Initialize the pipes
for(int i=0;i<MAX;i++){
pipes[i]=-1;
}
//OPEN NAMED PIPE FOR READING
int fd;
if ((fd= open(PIPE_NAME, O_RDONLY)) < 0) {
perror("Cannot open pipe for reading: ");
exit(0);
}
pipes[0]=fd;
char received[512];
//Loop that waits for data to appear in the pipes
while(1){
fd_set read_set;
FD_ZERO(&read_set);
for (int channel=0;channel<MAX;channel++) {
FD_SET(pipes[channel], &read_set);
}
if (select(pipes[MAX-1]+1, &read_set, NULL, NULL, NULL) > 0 ) {
if (FD_ISSET(pipes[0], &read_set)) {
read(pipes[0],received,sizeof(received));
printf("[Named pipe] Received %s.\n",received);
}
//Unamed pipes are still not created!
for (int channel=1;channel<MAX;channel++) {
if (FD_ISSET(pipes[channel], &read_set)) {
read(pipes[channel],received,sizeof(received));
printf("[Unamed pipe] Received %s.\n",received);
}
}
}
}
}
int main(){
signal(SIGINT, sigint);
if(fork()==0){
newProcess();
exit(0);
}
unlink(PIPE_NAME);
printf("Creating named pipe.\n");
if ((mkfifo(PIPE_NAME, O_CREAT|O_EXCL|0600)<0) && (errno!= EEXIST)) {
perror("Cannot create pipe: ");
exit(0);
}
printf("Named pipe created.\n");
int named_pipe_fd;
printf("Opening named pipe.\n");
if ((named_pipe_fd = open(PIPE_NAME, O_WRONLY)) < 0) {
perror("Cannot open pipe for writing: ");
exit(0);
}
printf("Named pipe open.\n");
char toSend[512];
//Sends data via the NAMED pipe to our child process
while(1){
scanf("%[^\n]%*c", toSend);
printf("[RaceSimulator] Sending (%s)\n",toSend);
write(named_pipe_fd, toSend, sizeof(toSend));
}
return 0;
}
Any help would be greatly appreciated!
The first argument to select should be the highest numbered file descriptor in the set. Since you've initialized them all to -1, except the zeroth, this call:
select(pipes[MAX-1]+1, &read_set, NULL, NULL, NULL)
will not work. You need to change that to:
select(fd+1, &read_set, NULL, NULL, NULL)
Or, once you've created the others, the highest among them.
I was trying to connect daemons (group of daemons without a leader) with main process as in title, the problem is that i have to send statement from each daemon(which are supporting SIGUSR1 signal) to main process, but i don' t even know how to do that, in my code i used mkfifo, but it's not working at all..
here is the main process source:
int main(int argc, char* argv[])
{
pid_t pid;
int i;
int n = atoi(argv[1]);
char c, message[255];
if(argc!=2){
printf("please insert one parametr\n");
return -1;
}
int fd = open("pipe", O_RDONLY);
if (fd == -1) {
perror("Failed open fifo to read");
return EXIT_FAILURE;
}
for( i = 0; i < n; i++) {
pid=fork();
if (pid==0){
printf("daemon created..\n");
}
else{
execl("daemons", "daemons", argv[1], NULL);
while(1){
sleep(2);
read(fd, message, c);
printf("P received: %s\n", message);
close(fd);
//read(fd[0], message, sizeof(message));
}
}
}
return 0;
}
and here is some source code in which i create daemons:
int fd = open("pipe", O_WRONLY);
if (fd < 0){
perror("cannot open fifo: ");
return EXIT_FAILURE;
}
if ( getppid() == 1 )
return 0;
/* Creating daemon */
pid[n] = fork();
if (pid[n] < 0)
exit(EXIT_FAILURE);
if (pid[n] > 0)
exit(EXIT_SUCCESS);
/* Setting leader of session */
sid = setsid();
if (sid < 0){
exit(EXIT_FAILURE);
}
/* fork one more time to make children
to have an opportunity to destroy
session leader */
for ( i = 0; i < n; i++){
pid[i] = fork();
if(pid[i] < 0){
printf("filed to fork...\n");
exit(EXIT_FAILURE);
}
if(pid[i]==0){
while(1){
sleep(2);
printf("Demon[%d]: My ID in pipe.%d\n", i+1, getpid());
signal(SIGUSR1, sigHandler);
write(fd, "Hi\n", strlen("Hi\n"));
close(fd);
}
}
chdir(".");
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
file = fopen("log_file.txt", "w+");
fclose(file);
umask(027);
}
at least i' m not sure about that i am creating daemons in good way..
And where i should put signal, which can be later executed?
Do you have any suggestions?
I'm trying to make a FIFO between two programs (one being a child process of the other) so that the child can write data back to the parent. Here's what I have so far:
(Parent)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MAX_BUF 1024
int main(int argc, char *argv[]) {
//number of seperate processes to create
int num_processes = 4;
int i = 0;
//FIFO accross processes
int fd;
char * myfifo = "/tmp/myfifo";
char buf[MAX_BUF];
/* create the FIFO (named pipe) */
mkfifo(myfifo, 0666);
for (i; i < num_processes; i++) {
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
exit(1);
}
else if (pid == 0) {
//child now exec's
char* args[] = {"./child", "args", NULL};
execv("./child", args);
}
}
printf("Parent doing stuff\n");
//Parent wait for child
printf("Parent waiting on child\n");
/* open, read, and display the message from the FIFO */
fd = open(myfifo, O_RDONLY);
if (fcntl(fd, F_GETFD) == -1) {
perror("fd failed");
exit(1);
}
read(fd, buf, MAX_BUF);
printf("Received: %s\n", buf);
//Wait for child processes to finish
int j = 0;
for (j; j < num_processes; j++) {
wait(NULL);
}
//Close FIFO
close(fd);
return 0;
}
(Child, created 4 times)
void main() {
printf("Completed\n");
//Create FIFO
int fd;
char * myfifo = "/tmp/myfifo";
/* write "Hi" to the FIFO */
fd = open(myfifo, O_WRONLY);
if (fcntl(fd, F_GETFD) == -1) {
perror("open failed");
exit(1);
}
write(fd, "Hi", sizeof("Hi"));
//close(fd);
/* remove the FIFO */
//unlink(myfifo);
}
Right now, "Completed" is being printed 4 times, showing that there are 4 seperate processes running as there should be. However, only one "Received: Hi" is printed in the terminal. How come I am not getting a FIFO response from the other processes?
Any help would be greatly appreciated!
You need to check fd and make sure the open succeeded. And note that it can only succeed once, because the first child will unlink(myfifo).
The parent should also wait for all of the children to finish before reading from the fifo. And the parent should read the fifo in a loop until the fifo is empty.
The problem in your code is that there are multiple child writing to the same FIFO.
As pointed out also by user3386109 you have to wait each child and read the FIFO.
here is a sample code:
//Wait for child processes to finish
int child_status = 0;
while (wait(&child_status) != -1) {
if (WIFEXITED (child_status)) {
fprintf (stdout, "the child process exited normally, with exit code %d\n", WEXITSTATUS (child_status));
// Read The buffer
read(fd, buf, MAX_BUF);
printf("Received: %s\n", buf);
}
else fprintf (stderr, "the child process exited abnormally\n");
}
I also suggest to pass to the child an id (this is just a sample add checks if needed):
else if (pid == 0) {
//child now exec's
char mypid[10];
snprintf(mypid, 10, "%d", i);
char* args[] = {"./child", mypid, NULL};
execv("./child", args);
sleep(1);
That each child read in argv[1]
int mypid = atoi(argv[1]);
Please, see also this post: C Named pipe (fifo). Parent process gets stuck
Solved by putting my read statements into the loop waiting for the child processes to finish:
/* open, read, and display the message from the FIFO */
fd = open(myfifo, O_RDONLY);
if (fcntl(fd, F_GETFD) == -1) {
perror("fd failed");
exit(1);
}
//Wait for child processes to finish
int j = 0;
for (j; j < num_processes; j++) {
read(fd, buf, MAX_BUF);
printf("Received: %s\n", buf);
wait(NULL);
}
//Close
close(fd);
return 0;
I'm assigned to make a program that creates three child processes as follows: A, B and C.
Process A reads data from a file and sends 4KB-long fragments to a message queue.
Process B reads these fragments from the queue, converts them and writes the
new data on the queue.
Finally, process C reads the converted string from the message queue and writes it on another file.
I used the fork() function to create them, and I'm having trouble generating the three child processes in a sequential order. When I run the program, usually processes B or C are created before A, and they can't read properly from the message queue because process A hasn't been generated yet.
How could I solve this problem?
This is the code I've been working on:
(Note: Two parameters must be added before running the program: ./program.exe source.txt destination.txt)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/msg.h>
#include <unistd.h>
#define TAM 4096
#define FILEKEY "/bin/cat"
#define KEY 4242
#define N_PROCESSES 3
typedef struct msgbuf{
long type;
char text[TAM];
}message;
int main (int argc, char *argv[]){
key_t key;
pid_t pid;
int msqid;
message env, enda, endb;
message rcv;
message conv;
message msg;
int buf_length;
FILE *f1=NULL;
FILE *f2=NULL;
char string[TAM], *receive;
int rc;
int i;
int status;
int p;
if(argc < 2){
printf("Incorrect command line arguments");
exit(-1);
}
p = getpid();
/*Opens files*/
f1 = fopen(argv[1], "r");
if(f1 == NULL){
exit(-1);
}
f2 = fopen(argv[2], "w");
if(f2 == NULL){
fclose(f1);
exit(-1);
}
/*Obtains key for message queue*/
key = ftok(FILEKEY, KEY);
if(key == -1){
fclose(f1);
fclose(f2);
exit(-1);
}
/*Creates message queue*/
msqid = msgget(key, IPC_CREAT | 0600);
if(msqid == -1){
fclose(f1);
fclose(f2);
exit(-1);
}
/*Message types*/
env.type = 1; /*Message from process A to process B*/
enda.type = 2; /*Process A has finished reading data from f1*/
conv.type = 3; /*Message from process B to process C*/
endb.type = 4; /*Process B has finished converting the string*/
/*Message size (4KB)*/
buf_length = sizeof(message)-sizeof(long);
/*Creates processes A, B and C*/
for ( i = 0; i < N_PROCESSES; i++){
pid = fork();
if(pid == -1){ /*Error*/
msgctl(msqid, IPC_RMID, (struct msqid_ds *)NULL);
fclose(f1);
fclose(f2);
exit(-1);
}else if (pid == 0 && i == 0){/*Process A*/
/*Reads from f1 while end of file is not reached*/
while (fgets(string, TAM, f1) !=NULL){
/*Copies string to env.text*/
strcpy(env.text, cadena);
/*Sends text fragments (4KB) to message queue*/
if(msgsnd(msqid, &env, buf_length, IPC_NOWAIT)<0){
msgctl(msqid, IPC_RMID, (struct msqid_ds *)NULL);
fclose(f1);
fclose(f2);
exit(-1);
}
}
/*Process A sends this message when there's no more data to read*/
if(msgsnd(msqid, &enda, buf_length, IPC_NOWAIT)<0){
msgctl(msqid, IPC_RMID, (struct msqid_ds *)NULL);
fclose(f1);
fclose(f2);
exit(-1);
}
exit(EXIT_SUCCESS);
}else if(pid == 0 && i == 1){/*Process B*/
/*Reads text fragments (4KB) from message queue*/
while (msgrcv(msqid, &rcv, buf_length, 1, IPC_NOWAIT)>0) {
/*Converts string*/
strcpy(receive, rcv.text);
for(i = 0; i < TAM; i++){
receive[i] = toupper(receive[i]);
}
strcpy(conv.text, receive);
/*Sends fragments of converted string to message queue*/
if(msgsnd(msqid, &conv, buf_length, IPC_NOWAIT)<0){
msgctl(msqid, IPC_RMID, (struct msqid_ds *)NULL);
fclose(f1);
fclose(f2);
exit(-1);
}
}
/*The loop finishes when there's an error or when there are no more type 1 messages to read*/
/*Reads type 2 message from process A*/
rc = msgrcv(msqid, &rcv, buf_length, 2, 0);
if( rc == -1){
msgctl(msqid, IPC_RMID, (struct msqid_ds *)NULL);
fclose(f1);
fclose(f2);
exit(-1);
}
/*Process B sends this message indicating that it has finished sending string fragments*/
if(msgsnd(msqid, &endb, buf_length, IPC_NOWAIT)<0){
msgctl(msqid, IPC_RMID, (struct msqid_ds *)NULL);
fclose(f1);
fclose(f2);
exit(-1);
}
exit(EXIT_SUCCESS);
}else if(pid == 0 && i == 2){/*Process C*/
/*Reads converted string fragments from message queue*/
while (msgrcv(msqid, &msg, buf_length, 3, IPC_NOWAIT)>0) {
/*Writes fragments on another file*/
if(fputs(msg.text, f2)<0){
exit(-1);
}
}
/*The loop finishes when there are no more fragments to write on f2*/
/*Then process C reads the last message sent from B*/
rc = msgrcv(msqid, &rcv, buf_length, 4, 0);
if( rc == -1){
msgctl(msqid, IPC_RMID, (struct msqid_ds *)NULL);
fclose(f1);
fclose(f2);
exit(-1);
}
exit (EXIT_SUCCESS);
}
}
/*Parent process waits for processes A, B and C*/
for (i=0; i<N_PROCESSES; i++) {
pid=wait(&status);
printf("Process %d with PPID = %d terminated\n", pid, p);
}
msgctl(msqid, IPC_RMID, (struct msqid_ds *)NULL);
fclose(f1);
fclose(f2);
return (EXIT_SUCCESS);
}
The processes are created in the order you specified, but the scheduler can schedule them in any order it likes, so you find code from process B executing before process A has finished, etc.
What I'd do to set up the situation you want is have 2 queues, one from A to B, the other from B to C. I'd create them all in the parent, to keep things simple.
Then I'd have the reading children do blocking reads (msgrcv() without IPC_NOWAIT), or I'd loop until I got a failure other than no data received.
The sending processes (A and B) would both put "and that's all" indicators into the queue when done, so the receivers would know they had everything.