can't put an advisory lock on a pipe?

I'd like to place an advisory write lock on a pipe file descriptor, but apparently that's not supported:
Code:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>


int main(int argc, char *argv[])
{
        struct flock set_lock = { l_type: F_WRLCK, l_whence: SEEK_CUR };
        if (fcntl(1, F_SETLKW, &set_lock, NULL) == -1)
        {
        fprintf(stderr, "%s\n", strerror(errno));
        return 1;
        }

        else fprintf(stderr, "fine\n");
}
Code:
> gcc test.c -o test
> ./test
[B]fine[/B]
> ./test | cat
[B]Bad file descriptor[/B]
I'm running FreeBSD 9.1-RELEASE (amd64.) I've also tried using flock(2) instead of fcntl(2).

Is there something wrong with my arguments? Can I enable it in my kernel? My objective is to properly interleave line output from multiple processes, which will often then be piped into another command.

Thanks!

Kevin Barry

edit: One workaround is to send the output to a temp file and tail -f that into the next process in the chain, although that adds a few more steps, maybe another session, and extra disk I/O to the process.
 
I'm not a programmer but both functions work on a file descriptor. You need to open the pipe first, get a file descriptor and then use flock(2) on it.
 
File descriptor 1 corresponds to standard output, which is always a valid file descriptor when a program starts.
Code:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>


int main(int argc, char *argv[])
{
[B]        struct stat stdout_stat;
        if (fstat(1, &stdout_stat) != 0)
        {
        fprintf(stderr, "fstat: %s\n", strerror(errno));
        return 1;
        }
        else
        fprintf(stderr, "%s\n", S_ISCHR(stdout_stat.st_mode)? "terminal" : (S_ISFIFO(stdout_stat.st_mode)? "pipe" : "other"));[/B]


        struct flock set_lock = { l_type: F_WRLCK, l_whence: SEEK_CUR };
        if (fcntl(1, F_SETLKW, &set_lock, NULL) == -1)
        {
        fprintf(stderr, "fcntl: %s\n", strerror(errno));
        return 1;
        }

        else fprintf(stderr, "fine\n");
}
Code:
> gcc test.c -o test
> ./test
[B]terminal
fine[/B]
> ./test | cat
[B]pipe
fcntl: Bad file descriptor[/B]
fstat would fail if the descriptor was invalid. The shell creates the pipe and replaces standard output with it before executing the binary. Thanks for the suggestion, though!

Kevin Barry
 
Back
Top