Reputation: 143
I have 2 different programs that I want to connect through a FIFO, and for some reason it isn't working right. The call to mkfifo
returns -1
which means that something didn't go right. Why would mkfifo
fail?
here is my code:
int main(){
pid_t pid;
int rv;
int fd;
int fifonum;
char *fifoName = "toServer2";
fifonum = mkfifo(fifoName, 0666);
if (fifonum<0){
printf("\n unable to create a fifo\n");
exit(-1);
}
fd = open(fifoName, O_WRONLY);
if( (pid=fork()) == -1 )
{
printf("fork error, exiting\n");
exit(1);
}
if(pid){
printf("this is the parent\n");
write(fd, "1", sizeof(int));
close(fd);
wait(&rv);
printf("child exited with this status %d\n", rv);
}else{
printf("this is the child");
if(execl("child", "child", NULL)==-1){
printf("execl error");
exit(1);
}
}
return 0;
}
Upvotes: 1
Views: 4255
Reputation: 567
I don't think fifonum = mkfifo(fifoName, 0666);
will overwrite a FIFO special file if it blocks, check to see if a file named toServer2 all ready exists. (I don't know what your child program does or if it does the clean up for FIFO file.)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int main(){
pid_t pid;
int rv;
FILE * fd;
FILE * od;
int fifonum;
char *fifoName = "toServer2";
fifonum = mkfifo(fifoName, 0666);
if (fifonum<0){
printf("%d\n", fifonum );
printf("\n unable to create a fifo\n");
exit(-1);
}
if( (pid=fork()) == -1 )
{
printf("fork error, exiting\n");
exit(1);
}
if(pid == 0 ){
int status;
fd = fopen(fifoName, "w");
printf("this is the parent\n");
fprintf(fd, "3");
fclose(fd);
wait(&rv);
status = remove(fifoName);
if( status == 0 )
printf("%s file deleted successfully.\n",fifoName);
else
{
printf("Unable to delete the file\n");
perror("Error");
}
}
else{
int c;
od = fopen(fifoName, "r");
//fgetc("%d", s);
c =fgetc(od);
printf("------%c-------", c );
fclose(od);
}
return 0;
}
Modified your program slightly to pass a 3 from parent process to child process, then clean up the special FIFO file.
Upvotes: 0
Reputation: 34829
The mkfifo
function will fail if the file already exists. One way to avoid the problem is to delete the file before calling mkfifo
. That way you start with a brand new, empty FIFO each time you run the program.
The general idea is to call stat
to see if the FIFO file exists, delete the file with unlink
if it exists, and then call mkfifo
to make a new FIFO.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
int createNewFifo( const char *fifoName )
{
struct stat stats;
if ( stat( fifoName, &stats ) < 0 )
{
if ( errno != ENOENT ) // ENOENT is ok, since we intend to delete the file anyways
{
perror( "stat failed" ); // any other error is a problem
return( -1 );
}
}
else // stat succeeded, so the file exists
{
if ( unlink( fifoName ) < 0 ) // attempt to delete the file
{
perror( "unlink failed" ); // the most likely error is EBUSY, indicating that some other process is using the file
return( -1 );
}
}
if ( mkfifo( fifoName, 0666 ) < 0 ) // attempt to create a brand new FIFO
{
perror( "mkfifo failed" );
return( -1 );
}
return( 0 );
}
int main( void )
{
if ( createNewFifo( "toServer2" ) < 0 )
exit( 1 );
// do something with the fifo ...
}
Upvotes: 2
Reputation: 62369
"Why would mkfifo
fail?" Direct from man 3 mkfifo
:
EACCES One of the directories in pathname did not allow search (execute) permission. EEXIST pathname already exists. This includes the case where pathname is a symbolic link, dangling or not. ENAMETOOLONG Either the total length of pathname is greater than PATH_MAX, or an individual filename component has a length greater than NAME_MAX. In the GNU system, there is no imposed limit on overall filename length, but some file systems may place limits on the length of a component. ENOENT A directory component in pathname does not exist or is a dangling symbolic link. ENOSPC The directory or file system has no room for the new file. ENOTDIR A component used as a directory in pathname is not, in fact, a directory. EROFS pathname refers to a read-only file system.
You'll have to check errno
to find out which of those is the case in your situation (or, as suggested elsewhere, use perror()
, which will consult errno
for you and select a suitable text string based on the value).
Upvotes: 0