liranahum
liranahum

Reputation: 143

Linux c programming fifo fails with no reason

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

Answers (3)

Hedge7707
Hedge7707

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

user3386109
user3386109

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

twalberg
twalberg

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

Related Questions