# can't put an advisory lock on a pipe?



## ta0kira (Feb 10, 2013)

I'd like to place an advisory write lock on a pipe file descriptor, but apparently that's not supported:
	
	



```
#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");
}
```


```
> 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.


----------



## SirDice (Feb 11, 2013)

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.


----------



## ta0kira (Feb 11, 2013)

File descriptor 1 corresponds to standard output, which is always a valid file descriptor when a program starts.
	
	



```
#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");
}
```


```
> 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


----------

