Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Bad file descriptor" when reading from FD 3 pointing to a temp file

Tags:

bash

My question is inspired by this SO answer.

Consider the script:

tmpfile=$(mktemp)
exec 3>"$tmpfile"
rm "$tmpfile"

>&3 cat <<EOS
line 1
line 2
line 3
EOS

cat <&3

You can play with it online here.

I expect it print out the 3 lines, but in fact I get a "Bad file descriptor" error.

Why does the above not work? How can it be altered so that it does?

Note: The error persists even if you delete the 3rd line: rm "$tmpfile".

like image 682
Jonah Avatar asked Mar 30 '19 20:03

Jonah


People also ask

What causes bad file descriptor?

Bad file descriptor; for example, I/O on a descriptor that has been closed or reading from a descriptor open only for writing (or vice versa). There are no child processes. This error happens on operations that are supposed to manipulate child processes, when there aren't any processes to manipulate.

What is bad file descriptor in Python?

When you don't allow the code to perform the functions related to the file descriptors and the methods used, a Bad File Descriptor Error arises in Python, indicating the wrong way of implementing the code.

What does bad file descriptor mean C?

In general, when "Bad File Descriptor" is encountered, it means that the socket file descriptor you passed into the API is not valid, which has multiple possible reasons: The fd is already closed somewhere. The fd has a wrong value, which is inconsistent with the value obtained from socket() api.

What is file descriptor in bash?

When bash starts it opens the three standard file descriptors: stdin (file descriptor 0), stdout (file descriptor 1), and stderr (file descriptor 2). You can open more file descriptors (such as 3, 4, 5, ...), and you can close them. You can also copy file descriptors. And you can write to them and read from them.

Why does the command get a bad file descriptor error?

The command reads (with read ()) from its stdin and gets the data that was written to the pipe by another process. But sometimes the command cannot read from its stdin stream and gets the "Bad file descriptor" error when trying to do so.

Why is my website unable to read what child say bad file descriptor?

“Error: unable to read what child say: bad file descriptor” – Causes & Fixes! In our experience handling website issues, we found 3 main reasons for this “ Error: unable to read what child say: bad file descriptor”. Sometimes, unexpected service crashes can lead to this error.

Why is my freopen file descriptor not working?

One possible source of issues is that "stdin" an "stdout" don't correspond necessarily with file descriptors 0 and 1 respectively. In many implementations of the runtime library freopen may change the file descriptor belonging to the FILE*.

How to deal with file descriptors 0 and 1?

I recommend you to use the "open", "close", "dup" etc... system call and deal with file descriptors 0 an 1 directly (or, better, the standard macros STDIN_FILENO and STDOUT_FILENO). Thanks for contributing an answer to Stack Overflow!


Video Answer


1 Answers

You only opened file descriptor 3 for writing, not reading. Change that line to

exec 3<>"$tmpfile"

and the bad file descriptor error will go away.

However, cat <&3 still won't produce any output, because the file pointer is still at the end of the file after the previous write. You would need to seek back to the beginning of the file to output what you just wrote, but bash doesn't provide a way to seek. The best you can do is reopen the file for reading, either by closing and reopening file descriptor 3 or by opening on another file descriptor.

Since the goal is to read the file after its only link has been removed, you'll have to open another file descriptor for reading before you delete it.

tmpfile=$(mktemp)
exec 3> "$tmpfile"
exec 4< "$tmpfile"

rm "$tmpfile"

>&3 cat <<EOS
line 1
line 2
line 3
EOS

cat <&4

Although 3 and 4 both refer to the same file, they each maintain a separate file pointer. There's no need to open 3 for reading and writing; you can write to the file on descriptor 3, then read the contents from descriptor 4.

like image 116
chepner Avatar answered Sep 29 '22 02:09

chepner