One last question. Have you filled out a PSF contribution form? If not, would you mind doing so? (Ideally you'd also tell me your bugs.python.org username, so I can check.)
On Thu, Jan 9, 2014 at 1:28 PM, Jonathan Slenders <[email protected]> wrote: > Super. It's working on my real application code. > The tests also run successfully on my ubuntu machine. > Thank you! > > > 2014/1/9 Guido van Rossum <[email protected]> >> >> OK, I think I get it now. I've worked up a simpler version of the >> patch, because I realized that the issue in _read_ready() is just that >> we don't want the EIO exception to be logged. Your test still passes. >> Let me know if your real code works with this version. >> >> https://codereview.appspot.com/48350043/ (patch set 2) >> >> raw download (for hg import): >> https://codereview.appspot.com/download/issue48350043_20001.diff >> >> On Tue, Jan 7, 2014 at 12:53 PM, Jonathan Slenders <[email protected]> >> wrote: >> > >> > >> > >> > 2014/1/7 Guido van Rossum <[email protected]> >> >> >> >> On Mon, Jan 6, 2014 at 10:57 PM, Jonathan Slenders >> >> <[email protected]> wrote: >> >> > It was the code I meant, not the test. >> >> > >> >> > But I just tested your revised version, and now the unit tests >> >> > succeed >> >> > here >> >> > as well. Thanks. >> >> >> >> OK, but I'm not at all convinced that catching EIO and treating it the >> >> same as EOF is correct. I don't even understand why I get that EIO. >> >> >> >> Could you show me some synchronous code (maybe using threads) showing >> >> how pyts are expected to work? >> > >> > >> > My guess is that we should usually close the master side first. >> > >> > I found at books.google.com, the linux programming interface, p1388: >> > """ >> > If we close all file descriptors referring to the pseudoterminal master, >> > then: >> > - if the slave device has a controlling process, a SIGHUP signal is sent >> > to >> > that process. >> > - a read() from the slave device returns end-of-of >> > - a write to the slave device failes with error EIO (on some other UNIX >> > implementations, write fails with the error ENXIO in this case.) >> > >> > If we close all file descriptors referring to the pseudoterminal slave, >> > then: >> > - a read() from the master device fails with error EIO (on some other >> > UNIX >> > implementations, a read() returns end-of-file in this case. >> > """ >> > >> > You are always going to attach an client application (e.g. an editor) on >> > the >> > slave side and have the terminal application (e.g. xterm) on the master >> > side. >> > >> > By default, you'll have the pty in line buffered mode. This means that >> > written characters on the master will be echo'ed back on the master (to >> > be >> > displayed). Only after enter has been pressed, becomes the whole line >> > available to be read on the slave. This way, the pseudo terminal >> > implements >> > some line editing functionality itself. A character written on the slave >> > is >> > always immediately available on the master. >> > >> > In raw mode, every key press on the master is immediately send to the >> > slave >> > side. The application on the slave is in that case also responsible for >> > displaying it, and should probably send some feedback by echoing back >> > the >> > received characters. >> > >> >> >> >> > The master should be non blocking indeed. I my project i called >> >> > ""io.open(self.master, 'wb', 0)"" >> >> >> >> There seems to be confusion here -- the 0 means non-*buffering*, it >> >> has no effect on *blocking*. >> >> >> > Sorry, you're right. I was confused. >> > >> >> >> >> > Something related about blocking vs. non blocking. I don't know how >> >> > these >> >> > file descriptors work exactly. >> >> >> >> Then how can you write working code using them? (Not a rhetorical >> >> question.) >> > >> > >> > What I meant is that often I feel there a still missing parts I don't >> > understand, but I know enough to build something useful. >> > >> >> > But I was now also able to use >> >> > connect_read_pipe to read from stdin which was really nice for me. >> >> >> >> Hm, this is really falling quite far outside the intended use case for >> >> asyncio. (Though well within that for the selectors module.) >> >> >> >> > (I really didn't like the executor solution that much.) >> >> >> >> I'm not aware of that solution -- is it in the docs somewhere? >> > >> > >> > Oh, just an executor running a blocking read in a while loop: >> > >> > def in_executor(): >> > while True: >> > c = stdin.read(1) >> > process_char(c) >> > >> > >> >> > However, if you make stdin non >> >> > blocking, stdout will automatically also become non blocking. >> >> >> >> Yeah, I see that too. I can't explain it; I suspect it's some obscure >> >> implementation detail of tty (or pty) devices. :-( >> > >> > >> > Maybe, like openpty(), stdin and stdout can actually be the same file >> > descriptor underneath if they are attached to a pseudo terminal, even if >> > they have different numbers. I learned that if you want to attach a >> > child >> > process to a newly created pseudo terminal, you do it by calling >> > openpty, >> > take the slave number, fork you own process, and in the fork use os.dup2 >> > to >> > copy that file descriptor to 0 and 1 (for stdout and stdin >> > respectively.) >> > >> > >> >> > But writing to >> >> > non blocking stdout seems like a bad idea, (you get "write could not >> >> > complete without blocking" errors everywhere.) >> >> >> >> So wrap a transport/protocol around stdin/stdout.That would seem to be >> >> the asyncio way to do it. You should probably wrap those in a >> >> StreamReader/StreamWriter pair -- the source code (streams.py) shows >> >> how to create those by hand, which is an intended use. >> > >> > >> > Thanks! That sounds really helpful. >> > >> >> > So what I do right now is to >> >> > make stdout blocking again before writing, during a repaint of the >> >> > app, >> >> > and >> >> > unblocking after writing. (Because this is all in the same thread as >> >> > the >> >> > event loop, it will be non blocking again when we get there.) >> >> >> >> Eew! :-( >> > >> > Yes, I know. >> > >> >> >> >> > It works nice, but what would be nice was to have a _set_blocking >> >> > method >> >> > available in unix_events which is symmetrical. (I why wouldn't we >> >> > make >> >> > them >> >> > public?) >> >> >> >> By the time you are passing your own file descriptors you should be >> >> mature enough to know how to make them non-blocking. Plus this is all >> >> UNIX-specific... Plus, create_pipe_transport() already calls it for >> >> you. >> >> >> >> Overall, perhaps you should just use the selectors module instead of >> >> asyncio? You might be happier with that... >> >> >> >> -- >> >> --Guido van Rossum (python.org/~guido) >> > >> > >> >> >> >> -- >> --Guido van Rossum (python.org/~guido) > > -- --Guido van Rossum (python.org/~guido)
