Wykres commitów

38 Commity (66f147a7616c73aef27977b76d977c255a3e5890)

Autor SHA1 Wiadomość Data
Paul Sokolovsky f6555bae97 uasyncio: On scheduling ready coro, unmark it as I/O-waiting.
Coros which are passed to .add_reader()/.add_writer() are marked as
I/O-bound using .pend_throw(False). Before scheduling it for normal
execution again, we need to unmark it with .pend_throw(None).
2017-12-14 19:14:42 +02:00
Paul Sokolovsky 04c0110319 uasyncio: open_connection: Initial hackish SSL support.
It performs handshake in blocking manner, hopes that writes
work without short writes, and hopes that non-blocking read
is implemented properly by ussl module (there're known issues
with axTLS module for example).
2017-12-09 18:07:32 +02:00
Paul Sokolovsky f704ac5817 uasyncio: StreamReader: Separate "poll socket" vs "I/O socket".
Poll socket is what's passed to uselect.poll(), while I/O socket is what's
used for .read(). This is a workaround of the issue that MicroPython doesn't
support proxying poll functionality for stream wrappers (like SSL, websocket,
etc.)
This issue is tracked as https://github.com/micropython/micropython/issues/3394

It may be that it's more efficient to apply such a workaround on uasyncio
level rather than implementing full solution of uPy side.
2017-11-05 18:01:21 +02:00
Paul Sokolovsky f81285ff4e uasyncio: Auto-unregister poll objects on POLLHUP/POLLERR.
POLLHUP/POLERR may be returned anytime (per POSIX, these flags aren't
even valid in input flags, they just appear in output flags). Subsequent
I/O operation on stream will lead to exception. If an application
doesn't do proper exception handling, the stream won't be closed, and
following calls will return POLLHUP/POLLERR status again (infinitely).
So, proactively unregister such a stream.

This change is questionable, because apps should handle errors properly
and close the stream in such case (or it will be leaked), and closing
will remove the stream from poller too.

But again, if that's not done, it may lead to cascade of adverse effects,
e.g. after eef054d98, benchmark/test_http_server_heavy.py regressed and
started and started to throw utimeq queue overflow exceptions. The story
behind it is: Boom benchmarker does an initial probe request to the app
under test which it apparently doen't handle properly, leading to
EPIPE/ECONNRESET on the side of the test app, the app didn't close the
socket, so each invocation to .wait() resulted in that socket being
returned with POLLHUP again and again. Given that after eef054d98, .wait()
is called on each even loop iteration, that create positive feedback in
the queue leading to it growing to overflow.
2017-11-05 17:12:12 +02:00
Paul Sokolovsky a191626c2e uasyncio: Add awriteiter() method.
Write piecewise content from iterable (usually, a generator).
2017-06-10 16:10:27 +03:00
Paul Sokolovsky a2097be138 uasyncio: Add own set_debug() function.
set_debug() from uasyncio.core doesn't have effect on the main uasyncio
package, so let them both have set_debug() function, and allow to enable
debug logging independently.
2017-06-08 02:51:29 +03:00
Paul Sokolovsky 75e1474ddf uasyncio: awrite: Use 3-arg .write(), accept offset/size too.
Use MicroPython .write() extension of passing offset/size to efficiently
spool buffers larger than socket output buffer. Also, make awrite()
accept these params too.
2017-06-07 03:09:34 +03:00
Paul Sokolovsky 16afc06b8c uasyncio: Switch to memory-efficient poll.ipoll() method.
As added in MicroPython 1.9.
2017-06-06 21:04:37 +03:00
Paul Sokolovsky 9a72e29564 uasyncio: Consistently use "if DEBUG and __debug__:" stanza.
To make sure this module can work without logging module imported, just
like uasyncio.core was made to.
2017-05-05 11:33:39 +03:00
Paul Sokolovsky a355801fb1 uasyncio: wait: Remove no longer needed "if", artifact of epoll impl. 2017-03-13 00:44:58 +03:00
Paul Sokolovsky 4fc72c6032 uasyncio: Remove "epoll" references from previous Linux-only implementation. 2017-03-12 16:42:02 +03:00
Paul Sokolovsky e3dac1d693 uasyncio: Allow to override queue length, while setting low default.
The default queue length is set to take under 0.5K RAM on 32-bit system.
A queue length can be passed to get_event_loop() to override it. This
change follows similar change in uasyncio.core.
2017-02-15 11:14:53 +03:00
Paul Sokolovsky 1bf1c74ae5 uasyncio: Use builtin uerrno module. 2017-01-28 01:55:40 +03:00
Paul Sokolovsky 7043ee0702 uasyncio: Implement StreamReader.readexactly().
With a unit test.
2017-01-28 01:04:21 +03:00
Paul Sokolovsky ec7b4b948b uasyncio: StreamReader.readline: Handle partial reads.
Now it will return a complete line regardless if it may take several
partial reads to do that. Test included.
2017-01-27 01:09:19 +03:00
Paul Sokolovsky a8d85e28d0 uasyncio: Fix partial reads in StreamReader.read/readline() methods.
If None (no data, would block) is received, need to wait for more data,
not just read it again immediately.
2017-01-26 22:20:29 +03:00
Daniel Mizyrycki 0f5d5cead7 uasyncio: Add minimum esp8266 support 2017-01-01 18:17:17 -08:00
Paul Sokolovsky 5403e0f710 uasyncio: Use DEBUG variable as imported from uasyncio.core.
Avoids heap allocation to render disabled debug logging strings.
2016-12-29 11:37:41 +03:00
Paul Sokolovsky f29be360c0 uasyncio: wait: Add workaround against heap alloc on empty iteration.
"for a in ():" unconditionally allocates heap so far, per
https://github.com/micropython/micropython/issues/2716 . So, test for
empty result before iterating over it.
2016-12-28 10:25:31 +03:00
Paul Sokolovsky 67d8e55dea uasyncio: Update for switching to utime.ticks_ms() timesource. 2016-11-13 04:39:52 +03:00
Paul Sokolovsky 5e10ef8adf uasyncio: Switch to builtin uselect.poll() object.
This is a big step towards supporting uasyncio on baremetal builds (and
on unix builds without FFI support).
2015-12-13 01:46:05 +02:00
Paul Sokolovsky b4b19f1dce uasyncio: Schedule simple I/O completion callbacks directly in event loop.
Simple == without args. This is expected action for them, and saves creation
of lambda just for that. Actually, probably all callbacks should be handled
this way.
2015-12-11 22:53:29 +02:00
Paul Sokolovsky 7cd53c8bf8 uasyncio: IORead/IOWrite syscalls don't return anything.
Their semantics is "wait for I/O of given type on object passed as argument",
so return value would be the same as argument, and thus no need to bother
to store/pass it around.
2015-12-10 00:29:10 +02:00
Paul Sokolovsky 17d96d35b5 uasyncio: Optimize reader/writer callbacks with no arguments.
Avoids allocating tuples.
2015-12-07 01:13:00 +02:00
Damien George 72d1f5ecfa uasyncio: Add StreamWriter.get_extra_info() to get peername.
This is the standard way of getting the name of the client that is
connected.
2015-06-03 13:25:27 +00:00
Paul Sokolovsky 99fa203686 uasyncio: StreamReader.close() -> .aclose().
Note: CPython asyncio lacks .close() on StreamReader at all, only StreamWriter
has it.
2015-01-04 21:47:06 +02:00
Paul Sokolovsky 20ddd54cb9 uasyncio: close() is synchronous method, ours is aclose() then. 2015-01-02 01:51:44 +02:00
Paul Sokolovsky 4fc39d86af uasyncio: start_server(): Add listen backlog arg, default to 10. 2014-11-06 17:14:50 +02:00
Paul Sokolovsky e9c7fa43f4 uasyncio: Set EpollEventLoop in a new way after .core refactor. 2014-11-04 02:52:31 +02:00
Paul Sokolovsky 0a529adfdc uasyncio: Use EPOLLONESHOT flag for add_reader/writer().
When we issue IORead/IOWrite syscall, we want get back notification just for
that call. But if we add fd to epoll, it will trigger continuously when the
condition is met. For example, a socket with empty write buffer will always
signal EPOLLOUT, regardless if we want to write to it now or not. This will
lead to situation when our coro will be woken up on such socket on *any*
syscall, and this syscall will get completely different socket as result (
or if syscall doesn't return socket - completely different result value).

So, to get semantics right, we need to make sure that for each IORead/IOWrite,
we get notified only once, and further events on socket are ignored until
we ask for them again. This is exactly what EPOLLONESHOT flag does.

The other alternative is to remove fd from epoll after each IORead/IOWrite,
but apparently EPOLLONESHOT is more performant way.

Yet another alternarnative would be to use edge-triggered mode of epoll,
but it has own peculiarities, like, after each event, client must make sure
that it is handled completely and reset, otherwise it may not trigger again,
even if there's unprocessed data. For example, if EPOLLIN|EPOLLET is used,
client must make sure that it reads all data available, until read() returns
EAGAIN. If it reads say just 10 bytes, then next time event simply won't
trigger (because it's edge event, which triggers on change like "no data" -
"data"; if we didn't read all data, the situation is "data" - "data", there's
no change in condition, and event is not triggered). Surely, that's not what
we want (at least not without restructuring how StreamReader works).

So, EPOLLONESHOT is the most obvious, and easiest to reason way to get needed
semantics.
2014-11-03 00:41:00 +02:00
Paul Sokolovsky 2a26ee80b7 uasyncio: Add checks that IOWrite() syscall return us socket we expect.
One check is commented by default to not hurt performance.
2014-11-03 00:40:52 +02:00
Paul Sokolovsky 610aa65cef uasyncio: Add StreamReader.close() method. 2014-10-29 00:55:10 +02:00
Paul Sokolovsky e8b99addbd uasyncio: Ignore ENOENT on remove_writer().
StreamWriter.awrite() first tries to write to an fd, and if that succeeds,
yield IOWrite may never be called for that fd, and it will never be added
to poller. So, ignore such error.
2014-10-27 00:30:40 +02:00
Paul Sokolovsky 0fcb1daa81 uasyncio: Log only if __debug__==True (i.e. no optimization). 2014-10-26 00:20:53 +03:00
Paul Sokolovsky 4a884ef849 uasyncio: Split off uasyncio.core dist module. 2014-10-24 01:00:53 +03:00
Paul Sokolovsky 2b582fd934 uasyncio: Cleanup module imports after split up. 2014-10-24 00:32:32 +03:00
Paul Sokolovsky b2130c84ce uasyncio: Split into "core" and "extended" modules. 2014-10-24 00:24:13 +03:00
Paul Sokolovsky a295825300 uasyncio: Convert to package. 2014-10-24 00:04:37 +03:00