Skip to content
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

Fix the inotify event handling in ReloadingYamlFileDisplayConfig::auto_reload() #3636

Merged
merged 3 commits into from
Oct 23, 2024

Conversation

AlanGriffiths
Copy link
Collaborator

ReloadingYamlFileDisplayConfig::auto_reload() incorrectly triggered on IN_CREATE.

The reason for that is that IN_CREATE and IN_CLOSE_WRITE events can often be read as pairs and we were not handling multiple events correctly.

Note:

This is a backport of the logic in ConfigFile's Watcher::handler(). Ideally, we'd unify the code. But that's awkward as Watcher currently only handles changes to a single file.

It would make sense to rework Watcher to have a single watch on the configuration directory and register multiple files with it.

@tarek-y-ismail
Copy link
Contributor

So here's what I understand you're doing:

  1. Whenever the file descriptor gets written to, you read the data (event data) into a buffer that you ensure is aligned and has space for the maximum filename length
  2. If the data read doesn't match the size of an inotify event, then some error has occured and we ignore this event
  3. Otherwise, we continue on, reinterpreting the data we read as an event, and making sure its either a write or a move event. (create event caused issues with empty config files)
  4. If the basename or a special suffixed basename are the subjects of the event, we handle the changes and update our display config
  5. We apply the new display config to the connected displays
  6. If there are other events, we handle them as well (not entirely sure about this one)

Is my understanding correct?

@AlanGriffiths
Copy link
Collaborator Author

3. Otherwise, we continue on, reinterpreting the data we read as an event, and making sure its either a write or a move event. (create event caused issues with empty config files)

We interpret the data we read as a series of events which we loop over.

The old code embodied a misconception that only a single event would be read. We never looked at the second or subsequent event in a series. That meant when writing a file (and getting an IN_CREATE, IN_CLOSE_WRITE pair) we were only seeing IN_CREATE, so that was (wrongly) added to the events that needed handling.

We don't want to try reading a file when it is created, because it may not have been written.

{
static size_t const sizeof_inotify_event = sizeof(inotify_event);

// A union ensures buffer is aligned for inotify_event
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could instead be

alignas(inotify_event) char buffer[sizeof(inotify_event) + NAME_MAX + 1];

right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, done to one of the copies of this logic, but not to the one directly below here?

RAOF
RAOF previously requested changes Oct 20, 2024
Copy link
Contributor

@RAOF RAOF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could be marking the inotify fd O_NONBLOCK and reading until we hit EAGAIN, but that'd just by a tiny optimisation.

Once the second union is replaced by alignas, this looks good to go.

(It also might be nice to deduplicate this logic into a helper, but there's only two copies at this point...)

{
static size_t const sizeof_inotify_event = sizeof(inotify_event);

// A union ensures buffer is aligned for inotify_event
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, done to one of the copies of this logic, but not to the one directly below here?

@AlanGriffiths
Copy link
Collaborator Author

(It also might be nice to deduplicate this logic into a helper, but there's only two copies at this point...)

Agreed: #3645

In fact there ARE three copies - the original is in Frame (and has the same bug)

Copy link
Collaborator

@Saviq Saviq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once the second union is replaced by alignas, this looks good to go.

@Saviq Saviq added this pull request to the merge queue Oct 23, 2024
Merged via the queue into main with commit 9812b80 Oct 23, 2024
39 checks passed
@Saviq Saviq deleted the fix-ReloadingYamlFileDisplayConfig branch October 23, 2024 11:44
@AlanGriffiths AlanGriffiths mentioned this pull request Nov 28, 2024
github-merge-queue bot pushed a commit that referenced this pull request Dec 3, 2024
# rc1

  * New upstream release 2.19.0

    - ABI summary:
      . miral ABI unchanged at 7
      . mircommon ABI unchanged at 10
      . mircore ABI unchanged at 2
      . miroil ABI unchanged at 5
      . mirplatform ABI bumped to 30
      . mirserver ABI bumped to 61
      . mirwayland ABI unchanged at 5
      . mirplatformgraphics ABI unchanged at 22
      . mirinputplatform ABI unchanged at 9

    - Enhancements:
. [x11-kiosk] defer fullscreening of applications until they are placed
once (#3670)
. [x11-kiosk] Ensure windows are placed and repainted on X11 "CONFIGURE"
(#3619)
      . [x11-kiosk] change enable-x11 default to true
      . Initial atomic-kms platform
      . [Wayland] Add support for xdg_activation_v1 (#3639)
      . Do not default window size (especially to weird values) (#3623)
. DesktopFileManager::resolve_app_id no longer returns an app id with a
.desktop file suffix (Fixes #3608)
. [Configuration] Split options into global and per-module configuration
(#3590)

    - Bugs fixed:
      . Ensure we always send an initial output enter (#3680)
      . Fix stuck-frame-after-mode-switch bug (#3673)
. Fix rendering of resized XWayland applications with client side
decorations (#3587)
      . Aspect ratios shouldn't contain zero (Fixes: #3663)
      . Use PkgConfig to find development headers (#3661)
. Fix the inotify event handling in
ReloadingYamlFileDisplayConfig::auto_reload() (#3636)
. The `miral::ConfigFile` "Watcher" can be destroyed before the main
loop (Fixes: #3612)
      . [xwayland] Don't allow clients to place X11 windows (#3622)
. Surfaces track scale changes on outputs they appear on. (Fixes: #3552)
      . New attached windows need to be placed (#3676)

----
[Test
Plan](https://canonical-mir.readthedocs-hosted.com/latest/how-to/how-to-test-mir-for-a-release/)

### Platforms
|| 24.04 | 24.10 |
|-|-|-|
| gbm-kms |@AlanGriffiths|@AlanGriffiths|
| atomic-kms |@AlanGriffiths|@AlanGriffiths|
| eglstream-kms |@tarek-y-ismail||
| eglstream-kms + gbm-kms hybrid |@tarek-y-ismail||
| x11 |@AlanGriffiths|@AlanGriffiths|
| wayland |@AlanGriffiths|@AlanGriffiths|
| virtual |@AlanGriffiths|@AlanGriffiths|

### Console Providers
|| 24.04 | 24.10 |
|-|-|-|
| vt |@AlanGriffiths|@AlanGriffiths|
| logind |@AlanGriffiths|@AlanGriffiths|
| minimal |@AlanGriffiths||

### Window Manager Examples
|| 24.04 | 24.10 |
|-|-|-|
| --window-manager=floating |@AlanGriffiths|@AlanGriffiths|
| --window-manager=tiling |@AlanGriffiths||
| -kiosk |@AlanGriffiths||
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants