Re: named pipe and "Text file busy"
by tuxz0r (Pilgrim) on Nov 25, 2007 at 06:30 UTC
|
I'm trying to recreate your problem, but if this is incorrect, let me know. I can't recreate your particular error, but I think this is what you are trying to do (again, correct me if I'm wrong).
This script opens the fifo if it doesn't exist and then starts the writer process in the background. It then opens the other end of the FIFO by cat'ing it to /dev/null. IF you don't open both ends of the FIFO, then the open call will block.
#!/bin/sh
# Make the FIFO (first time only)
if [ ! -p "file.fifo" ]
then
mkfifo file.fifo
fi
# run script to write to FIFO and wait for it to finish
./writefifo.sh &
cat file.fifo >/dev/null # open other end
wait && echo "writer done"
rm -f file.fifo
exit 0
This is the writer script, which simply echo's a line to the FIFO, sleeps a bit and then exits.
#!/bin/sh
echo "a line to the fifo" >> file.fifo
sleep 5
This seems to work fine for me, even when I Control-C the main script before the writer finishes. Do you have any processes still running after your primary Ctrl-C that may be blocking on an open call?
---
echo S 1 [ Y V U | perl -ane 'print reverse map { $_ = chr(ord($_)-1) } @F;'
Warning: Any code posted by tuxz0r is untested, unless otherwise stated, and is used at your own risk.
| [reply] [d/l] [select] |
|
|
yes, you're right with your example: in my case instead of cat file.fifo >/dev/null i use my Perl script to read the FIFO.
Your example works fine for me as well, so i believe there's smth wrong with my Perl script.
I've checked there are no processes left after Ctrl-C the script.
Here's the sequence of steps i perform:
1. Start the script that opens file.fifo and wait for data to arrive
2. in the shell: echo "test" > file.fifo. This works fine, the script reads "test" with no problems
3. Ctrl-C my Perl script
4. do echo "test" > file.fifo again. Result - "Text file busy"
| [reply] |
|
|
| [reply] |
|
|
|
|
|
Re: named pipe and "Text file busy"
by TOD (Friar) on Nov 25, 2007 at 04:31 UTC
|
| [reply] [d/l] |
|
|
Thanks for this, but that's what i've got atm. I've installed my routine for $SIG(INT) and inside i close the pipe explicitly, however, this does not help and the behaviour is the same: after the script terminates, doing echo "message" > pipename or trying to write with any other program results in "Text file busy". Under normal circumstances a writing program should just block (unless the pipe is open in non-blocking mode), given that there are no readers (the script has been terminated). Any ideas? Thanks.
| [reply] |
Re: named pipe and "Text file busy"
by KurtSchwind (Chaplain) on Nov 25, 2007 at 06:58 UTC
|
Do you actually need the FIFO to stay around between runs? Or can you just code a delete before the create if it already exists?
--
I used to drive a Heisenbergmobile, but every time I looked at the speedometer, I got lost.
| [reply] |
|
|
yes, i do need it to stay between runs, unfortunately :(
| [reply] |
Re: named pipe and "Text file busy"
by sgt (Deacon) on Nov 25, 2007 at 21:42 UTC
|
There is a contract for the use of a named pipe. I will suppose un*xlike and to simplify I will not talk about non-blocking. For pipes the
default is blocking.
- You need a reader and usually the reader is a long-running process.
- The reader will block on read as soon as it opens.
If there is no reader any writer will block.
- Remember it *is* a pipe so what gets in must get out...
If you write more than a certain maximum number of bytes input is likely to be intermixed between the writers.
If the reader does not process the input quickly enough then eventually a writer will be blocked and then all the other writers, so you need some flow analysis or special janitor processes.
So do you have a permanent reader? If you have a read-once reader
the behavior you seem to be experiencing is *normal*.
Can it be somehow that the pipe is opened by the two threads?
Can you check with lsof or similar the processes that maintain a descriptor opened to the named pipe.
If you had posted some code we might have been able to help better.
% steph@ape (/home/stephan) %
% cat reader.sh
#!/bin/ksh
trap 'exit 0' INT
pipe=named_pipe outfile=out
[[ -p $pipe ]] || mkfifo $pipe
exec 0<$pipe
while dd if=$pipe bs=64 count=1 >> $outfile
do
print .processing
sleep 2
done
% steph@ape (/home/stephan) %
% jobs
[1] + Running ./reader.sh &
cheers --stephan
| [reply] [d/l] |
|
|
Thanks I should note that "text file busy" only happens after i open the pipe with my perl script and terminate it. After that, this error occurs irrespective of whether later i've got the script (reader) running together with the writer or a writer by itself.
I've checked the pipe is open by one thread only and the descriptor is not maintained after i exit the script.
The code snippet is quite basic:
my $alertsthr = threads->new(\&al_thread);
$SIG{'INT'} = 'CLEANUP';
sub CLEANUP {
print "\nClosing pipe\n";
close PIPE;
exit();
}
sub al_thread
{
my $myline;
while (1) # keep reading from the pipe until we're killed
{
print "$config->{FIFO} open\n" if $config->{VERBOSE};
open (PIPE, "$config->{FIFO}") or die "Could not open the input
+pipe $config->{FIFO}\n";
while($myline = <PIPE>)
{
print "read $myline\n" if $config->{VERBOSE};
process_message($myline);
}
print "$config->{FIFO} EOF\n" if $config->{VERBOSE};
}
}
| [reply] [d/l] |
|
|
Is there really any guarantee that the SIGINT will be caught by the right thread? you could try forking which would be ok in this respect.
Then the ETXTBSY (errno 26) is weird. I see the error only with open(2) but not read(2) or write(2). Cannot reproduce it on hp testdrive.
cheers
--stephan
| [reply] |