whisper
whisper

Reputation: 95

Linux C use mkfifo file descriptor with select

I'm planing to monitor the fifo and stdin with select function, but it always block the code flow even though O_NONBLOCK is configured, would anyone help check about it please ?

I'm not sure it's the code issue or solution is not a right direction to try, thanks in advance.

There are 2 problems :

  1. stdin is not able to read when the program start.
  2. FD_ISSET(pipe_fd, &fds) will continuously be true, if do not close pipe_fd manually.
    if (FD_ISSET(pipe_fd, &fds)) {
        read_pipe(pipe_fd);
        close_pipe(pipe_fd); // continously triggered if not close here
    }
    

Here is the full code.

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#define BUF_SZ          128
#define FIFO_BUF_SZ     128

#define PIPE_PATH       "./test_fifo"

int create_pipe_fd()
{
    char *f_path = PIPE_PATH;
    int ret;

    // creating the named file(FIFO)
    // mkfifo(<pathname>, <permission>)
    //ret = mkfifo(f_path, 0666);
    ret = mkfifo(f_path, 0666);

    if (ret < 0) {
        printf("create fifo file failed, err = %s\n", strerror(errno));
    }
}

int open_pipe()
{
    char *f_path = PIPE_PATH;
    int fd;

    // open fifo for read only
    fd = open(f_path, O_RDONLY);

    // non blocking mode
    if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
        printf("mode set failed, err = %s\n", strerror(errno));
    }

    return fd;
}

int read_pipe(int fd)
{
    uint8_t buf[FIFO_BUF_SZ];
    ssize_t cnt;
    size_t end;
    size_t sz = sizeof(buf);

    cnt = read(fd, buf, sz);

    end = (cnt > (sz - 1)) ? (sz - 1) : cnt;

    buf[end] = '\0';

    printf("read pipe = %s\n", buf);
}

void close_pipe(int fd)
{
    close(fd);
    //printf("pipe closed.\n");
}

uint16_t read_stdin()
{
    char *line = NULL;
    size_t len = 0;
    ssize_t lineSize = 0;
    uint8_t stdin_buf[BUF_SZ];

    lineSize = getline(&line, &len, stdin);

    printf("[stdin %zu bytes] : %s", lineSize, line);

    if (0 == strncmp("stop", line, strlen("stop"))) {
        return 0;
    }

    free(line);

    return (int)lineSize;
}

int main()
{
    fd_set fds;
    int max_fd = 0;
    int pipe_fd = -1;
    uint16_t bytes;

    printf("start.\n");

    // get pipe file descriptor
    //pipe_fd = create_pipe_fd();
    create_pipe_fd();

    pipe_fd = open_pipe();
    //max_fd = pipe_fd > max_fd ? pipe_fd : max_fd;

    while (1) {
        FD_ZERO(&fds);

        // stdin
        FD_SET(0, &fds);

        //pipe_fd = open_pipe();
        if (pipe_fd > 0) {
            FD_SET(pipe_fd, &fds);
        }

        max_fd = pipe_fd > max_fd ? pipe_fd : max_fd;

        select(max_fd + 1, &fds, NULL, NULL, NULL);

        if (FD_ISSET(0, &fds)) {
            bytes = read_stdin();
            if (0 == bytes) {
                break;
            }
        }

        if (FD_ISSET(pipe_fd, &fds)) {
            read_pipe(pipe_fd);
            close_pipe(pipe_fd);
        }
    }

_EXIT:
    if (pipe_fd) {
        close_pipe(pipe_fd);
    }

    printf("exit.\n");
}

Upvotes: 0

Views: 441

Answers (0)

Related Questions