• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mosquito / caio / 30852629971

03 Aug 2026 08:58PM UTC coverage: 90.977%. First build
30852629971

Pull #69

github

web-flow
Merge 09144c6b3 into d43cac632
Pull Request #69: Fix segfault, hang, and ~30 real bugs across all 4 I/O backends

83 of 91 new or added lines in 5 files covered. (91.21%)

363 of 399 relevant lines covered (90.98%)

11.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.67
/caio/linux_uring_asyncio.py
1
from .asyncio_base import AsyncioContextBase
14✔
2
from .linux_uring import Context, Operation
14✔
3

4

5
class AsyncioContext(AsyncioContextBase):
5✔
6
    OPERATION_CLASS = Operation
5✔
7
    CONTEXT_CLASS = Context
5✔
8

9
    def _create_context(self, max_requests):
5✔
10
        context = super()._create_context(max_requests)
5✔
11
        self.loop.add_reader(context.fileno, self._on_read_event)
5✔
12
        return context
5✔
13

14
    def _on_done(self, future, result):
5✔
15
        if future.done():
5✔
16
            return
3✔
17
        future.set_result(True)
5✔
18

19
    def _destroy_context(self):
5✔
20
        self.loop.remove_reader(self.context.fileno)
5✔
21

22
    def _on_submitted(self):
5✔
23
        # Flush immediately after every submit.
24
        #
25
        # Non-SQPOLL (default): flush() calls io_uring_enter() which completes
26
        # page-cache ops inline, then drain_cq() fires futures *before* the
27
        # caller reaches `await future` — so the coroutine never suspends for
28
        # those ops.  Truly async ops (real disk) leave the future unset; the
29
        # coroutine suspends and the eventfd wakes it when the kernel is done.
30
        #
31
        # SQPOLL: flush() wakes the kernel thread if sleeping, then drain_cq().
32
        # Same "fast path" benefit when the thread has already completed the op.
33
        self.context.flush()
5✔
34

35
    def _on_read_event(self):
5✔
36
        """Handle completions signalled via the eventfd."""
37
        # poll() raises BlockingIOError whenever the eventfd's counter
38
        # reads as zero - possible even right after epoll reported this fd
39
        # readable (e.g. the kernel coalesces multiple completions into one
40
        # counter increment, and the ones beyond the first can still be
41
        # landing in the CQ ring at the moment poll() runs). Letting that
42
        # exception escape used to skip process_events() entirely for this
43
        # wakeup - draining is independent of the eventfd count (it reads
44
        # the CQ ring directly), so a stale/absent counter is never a
45
        # reason to skip it, only silently stranding whatever was already
46
        # completed with no other event left to wake this Context up
47
        # again. Confirmed to actually hang a real (non-tmpfs) benchmark
48
        # run this way - inline tmpfs completions never exercise this path
49
        # at all, since they never reach the eventfd in the first place.
50
        try:
5✔
51
            self.context.poll()
5✔
NEW
52
        except BlockingIOError:
×
NEW
53
            pass
×
54
        while self.context.process_events():
5✔
55
            pass
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc