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.