Reputation: 673
How can I close a program if a pipe stream is idle for a period of time?
Say for instance:
someprogram | closeidlepipe -t 500 | otherprogram
Is there some program closeidlepipe
that can close if idle for a period (-t 500
)?
timeout
can close after a period, but not with the "idle" distinction.
UPDATE
It is important to note that someprogram
outputs an endless stream of binary data. The data may contain the null character \0
and should be piped verbatim.
Upvotes: 4
Views: 184
Reputation: 43317
Here's the general form of the heart of a program that does this.
while(1) {
struct timeval tv;
tv.m_sec = 0;
tv.m_usec = 500000;
int marker = 1;
select(1, &marker, NULL, NULL, &tv);
if (marker == 0) exit(1);
char buf[8192];
int n = read(0, buf, 8192);
if (n < 0) exit(2);
char *b = buf;
while (n)
{
int l = write(1, b, n);
if (l <= 0) exit(3);
b += l;
n -= l;
}
}
Upvotes: 1
Reputation: 531808
The builtin read
has a timeout option -t
.
someprogram |
while :; do
IFS= read -d'' -r -t 500 line
res=$?
if [[ $res -eq 0 || )); then
# Normal read up to delimiter
printf '%s\0' "$line"
else
# Either read timed out without reading another null
# byte, or there was some other failure meaning we
# should break. In neither case did we read a trailing null byte
# that read discarded.
[[ -n $line ]] && printf '%s' "$line"
break
fi
done |
otherprogram
If read
times out after 500 seconds, the while
loop will exit and the middle part of the pipeline closes. someprogram
will receive a SIGCHLD
signal the next time it tries to write to its end of that pipe, allowing it to exit.
Upvotes: 1