Skip to content

extmod/asyncio/event.py: Fix ThreadSafeFlag.ioctl return. #12443

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 29, 2023

Conversation

jimmo
Copy link
Member

@jimmo jimmo commented Sep 14, 2023

iobase_ioctl expects that an ioctl method must return an integer, and will raise otherwise.

This was tripping up aioble on Unix, where the new hybrid modselect.c implementation will attempt to extract a file descriptor from the pollable via ioctl(MP_STREAM_GET_FILENO).

However, ThreadSafeFlag's ioctl only supported MP_STREAM_POLL, and returned None otherwise.

This makes it return -1 (to match tests/extmod/select_poll_custom.py). It should probably be -22 (corresponding to MP_EINVAL), but the value is never checked, and MP_EINVAL can be a different value on different ports.

This work was funded through GitHub Sponsors.

@jimmo
Copy link
Member Author

jimmo commented Sep 14, 2023

@dpgeorge This PR solves the problem and aioble works now, but it's worth noting that this actually triggered a seg fault, because the nlr raise in the middle of poll_set_add_obj left the element in poll_set->map partially initialised (specifically elem->value is NULL, because that happens right at the end).

This might be a case for the new nlr jump callback, to cleanup if the ioctl failed? i.e. it seems wrong that poller.register can raise and leave the poller in an invalid state if the pollable's ioctl raises.

@github-actions
Copy link

Code size report:

   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:    +0 +0.000% standard
      stm32:    +0 +0.000% PYBV10
     mimxrt:    +0 +0.000% TEENSY40
        rp2:    +0 +0.000% RPI_PICO
       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS

@jimmo
Copy link
Member Author

jimmo commented Sep 14, 2023

Added a change to the ThreadSafeFlag test to make it no longer sensitive to the order that the scheduler runs relative to the main code. e.g. the ioctl(MP_STREAM_GET_FILENO) call could trigger the scheduler.

@codecov
Copy link

codecov bot commented Sep 14, 2023

Codecov Report

Merging #12443 (3e204b8) into master (c854d0e) will decrease coverage by 0.01%.
The diff coverage is n/a.

❗ Current head 3e204b8 differs from pull request most recent head fae83a6. Consider uploading reports for the commit fae83a6 to get more accurate results

@@            Coverage Diff             @@
##           master   #12443      +/-   ##
==========================================
- Coverage   98.39%   98.38%   -0.01%     
==========================================
  Files         158      158              
  Lines       20939    20940       +1     
==========================================
  Hits        20602    20602              
- Misses        337      338       +1     

see 4 files with indirect coverage changes

@dpgeorge dpgeorge added the extmod Relates to extmod/ directory in source label Sep 29, 2023
@dpgeorge
Copy link
Member

it's worth noting that this actually triggered a seg fault, because the nlr raise in the middle of poll_set_add_obj left the element in poll_set->map partially initialised (specifically elem->value is NULL, because that happens right at the end).

Yes I was aware of this issue when writing the code. It was really hard to solve so I just left it and instead added the comment in poll_set_add_obj:

            // If an exception is raised below when adding the new object then the map entry for that
            // object remains unpopulated, and methods like poll() may crash.  This case is not handled.

This might be a case for the new nlr jump callback, to cleanup if the ioctl failed?

The poll change was made before nlr jump callbacks were added, so, yes, maybe we can use nlr jump callbacks to fix this issue. It's low priority though, because a well-behaved program shouldn't crash in this way.

iobase_ioctl expects that an ioctl method must return an integer, and will
raise otherwise.

This was tripping up aioble on Unix, where the new hybrid modselect.c
implementation will attempt to extract a file descriptor from the pollable
via ioctl(MP_STREAM_GET_FILENO).

However, ThreadSafeFlag's ioctl only supported MP_STREAM_POLL, and returned
None otherwise.

This makes it return `-1` (to match tests/extmod/select_poll_custom.py). It
should probably be `-22` (corresponding to MP_EINVAL), but the value is
never checked, and MP_EINVAL can be a different value on different ports.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
1. Remove the skip for detecting support for polling user-defined objects
   as this is always possible now on all ports.
2. Don't print when the scheduled task runs as the ordering of this
   relative to the other prints is dependent on other factors (e.g. if
   using the native emitter).

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
@dpgeorge dpgeorge force-pushed the asyncio-threadsafeflag-ioctl branch from 3e204b8 to fae83a6 Compare September 29, 2023 07:59
@dpgeorge dpgeorge merged commit fae83a6 into micropython:master Sep 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extmod Relates to extmod/ directory in source
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants