views:

71

answers:

6

If I open a a file as os.open( '/dev/ttyS2', O_RDWR | O_NDELAY ), is there any way that I can check when my 'write()' commands have finished? Or, can I open a file for non-blocking read but blocking write?

A: 

OS API write() returns count of written bytes. Checking this value against size of your input you can see when all input is sent.

Victor Sorokin
A: 

Open two file descriptors to the same location - one for non-blocking reads and the other for blocking writes.

Computer Guru
A: 

Have you tried os.fsync(fd)?

Karl Bielefeldt
does fsync work for a serial device?
Falmarri
On further research, apparently not. Looks like camh's tcdrain is the way to go.
Karl Bielefeldt
+1  A: 

The O_NDELAY flag always affects both reading and writing. To achieve a blocking write on a non-blocking file you can select (Python module) the file and write when it becomes writable in a loop.

Helmut
Are you sure select.select() will block with a non-blocking file descriptor? Or did you mean a different select module method
Falmarri
@Falmarri: Yes, `select()` blocks with non-blocking file descriptors.
caf
+3  A: 

If you are writing to a tty (as you are in your example), you can use termios.tcdrain to wait until all written bytes have been transmitted.

Your write systems calls will still be non-blocking, so you will need to handle EWOULDBLOCK/EAGAIN errors, and use select(2), poll(2) or epoll(7) to know when you can write to the file descriptor. These are designed to be used with non-blocking file descriptors.

camh
+3  A: 

You have a misunderstanding of what non-blocking means. It does not imply asynchronous operation - you can have any combination of asynchronous/synchronous and blocking/non-blocking.

A write() just hands data off to the kernel to take care of. When write() returns successfully, the kernel has now taken care of the data - this is true regardless of whether the file descriptor is blocking or non-blocking. Whether or not the kernel has actually finished writing it at this point is a separate matter (usually, the answer is "no" - most file descriptors are asynchronous).

A write() cannot complete if the kernel has no more room to buffer the data you want to write, and this is the case that is affected by non-blocking versus blocking - in the blocking case, the write() will block until space is available. In the non-blocking case, write() will return an error (EAGAIN), and it is up to you to retry it later.

If you wish to wait until all data written to a terminal device has actually been sent to the hardware, use tcdrain() - but this is likely to be unnecessary. Alternatively, if you wish write() to block until your data is accepted by the kernel, then you can use fcntl() to temporarily set the file descriptor to blocking.

caf
This is not quite correct. Even in nonblocking mode, a `write` to ordinary files and possibly certain devices will "block" pending the availability of buffer space. Nonblocking mode only works correctly for sockets and an implementation-specific collection of other file descriptor types (likely including terminal devices/serial ports).
R..
@R.: A `write` to ordinary files that has to wait does not block - it "Disk Waits".
caf