Skip to content

Add flag to allow independent instances of policy editor#295

Open
ffe4 wants to merge 1 commit intoQubesOS:mainfrom
ffe4:main
Open

Add flag to allow independent instances of policy editor#295
ffe4 wants to merge 1 commit intoQubesOS:mainfrom
ffe4:main

Conversation

@ffe4
Copy link
Copy Markdown

@ffe4 ffe4 commented Feb 8, 2026

Fixes #9913 by allowing for multiple independent instances of the policy editor.

By default, when a GTK application is already running and the application is launched again, the arguments are passed to the already running instance.

Methods in policy editor, such as _quit(), act on the application level, not on a window or panel, leading to unexpected behavior when opening multiple windows of the editor, like closing all windows of the application when trying to only close one.

Since we do not need to share any state between multiple editor instances we can set the NON_UNIQUE [1] flag to put each new editor instance into its own process.

We could also keep everything in the same process and update the implementation to handle everything correctly, but unless we want to implement tabs or something similar, I don't know whether that has any advantages.

[1] https://docs.gtk.org//gio/flags.ApplicationFlags.html#non_unique

Writing tests for this seemed more trouble than it's worth, so I only tested it against the existing suite and manually on dom0. If you need tests I'll try to write some after I figure out how to set up the rest of the dev environment.

Before:

policyed-unique

All windows get assigned to the same instance / process.
Opening two windows and then closing one of them quits the whole process.
Undo in one window reverts the latest change done in any window.

After:

policyed-non-unique

Each instance / process is independent.

By default, when a GTK application is already running and the
application is launched again, the arguments are passed to the
already running instance.

Methods in policy editor, such as `_quit()`, act on the application
level, not on a window or panel, leading to unexpected behavior when
opening multiple windows of the editor, like closing all windows
of the application when trying to only close one.

Since we do not need to share any state between multiple editor
instances we can set the NON_UNIQUE flag to put each new editor
instance into its own process.

https://docs.gtk.org//gio/flags.ApplicationFlags.html#non_unique
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.95%. Comparing base (a89069d) to head (4dd58aa).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #295      +/-   ##
==========================================
- Coverage   92.98%   92.95%   -0.04%     
==========================================
  Files          64       64              
  Lines       13291    13291              
==========================================
- Hits        12359    12355       -4     
- Misses        932      936       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ffe4 ffe4 marked this pull request as ready for review February 8, 2026 21:43
@marmarta
Copy link
Copy Markdown
Member

This makes perfect sense and also: thank you for the detailed and well-made PR and commit description!

@ben-grande
Copy link
Copy Markdown

What happens when two instances edit the same file and you try to save both instances? Does not overwrite the other? If yes, please add a lock per file.

@marmarta
Copy link
Copy Markdown
Member

What happens when two instances edit the same file and you try to save both instances? Does not overwrite the other? If yes, please add a lock per file.

I don't think it's an unreasonable behavior to have the later save win. Don't think this is necessary.

@ffe4
Copy link
Copy Markdown
Author

ffe4 commented Feb 14, 2026

What happens when two instances edit the same file and you try to save both instances? Does not overwrite the other? If yes, please add a lock per file. I would agree with @marmarta that letting the last save win should be okay. It is the behavior of many other text editors as well, and more importantly, the current behavior is even more confusing.

In this PR the last save wins.

The editor uses the PolicyClient from qrexec to fetch and replace the policies, so we do not actually have access to the file in order to lock it. I would agree with @marmarta that letting the last save win should be okay, especially since the current behavior is even more confusing.

That being said, if we still want to prevent accidental overwrites we have to handle them in the editor (assuming we want to keep the qrexec stuff). One option would be to keep everything in one instance, fix the handling of multiple windows, so that Saves, Undos, etc. work properly and then prevent the application from opening the same file multiple times. I would assume that shouldn't be hard to implement, but I'm also not really familiar with GTK.

Another option would be to keep a copy of the contents of the policy file on load and on save. We could then fetch the contents again before each save, check whether they match our local copy, and prompt the user for confirmation if they do not. This might be a quick fix but seems like it could break for any number of reasons, considering that we do not actually edit the file directly.

@ben-grande
Copy link
Copy Markdown

ben-grande commented Feb 14, 2026 via email

@ben-grande
Copy link
Copy Markdown

ben-grande commented Feb 14, 2026 via email

@ben-grande
Copy link
Copy Markdown

ben-grande commented Feb 14, 2026 via email

@ben-grande
Copy link
Copy Markdown

ben-grande commented Mar 4, 2026

In this PR the last save wins.

That doesn't seem to be the case. Did you test it? I just tested and it shows

Failed to save policy

An error occurred while trying to save the policy file:
Internal error. See /var/log/qubes/policy-admin.log in dom0 for details

To get out of this situation, user has to copy their changes from the buffer to the clipboard, click on File -> Open -> SAME_FILE, paste changes to the buffer. Therefore I suggest once again a lock per file, because relying on the user to do the right thing is not nice.


On another point, this error message is bad, it could be improved by catching qrexec.policy.admin.PolicyAdminTokenException and displaying a proper error message with recommendations of what to do. but the exception is never sent to the client, what is sent is

subprocess.CalledProcessError: Command '['/usr/bin/qrexec-client', '-d', 'dom0', 'DEFAULT:QUBESRPC policy.Replace+30-user dom0']' returned non-zero exit status 2.

@ben-grande
Copy link
Copy Markdown

so we do not actually have access to the file in order to lock it.

Just to be clear, it is not "locking the file" on the file system level, but locking the editor to only have unique files.

@ffe4
Copy link
Copy Markdown
Author

ffe4 commented Mar 4, 2026

In this PR the last save wins.

That doesn't seem to be the case. Did you test it? I just tested and it shows

Failed to save policy

An error occurred while trying to save the policy file:
Internal error. See /var/log/qubes/policy-admin.log in dom0 for details

I wasn't able to properly get the dev environment running with Qubes Builder, so I only tested it in dom0 in my regular Qubes installation. Maybe I had different versions of something, I certainly didn't get an error, as far as I could tell.

Since I didn't know about the tokens being used in the background to prevent accidental overwrites, I indeed assumed you were talking about file system locks before.

If we want to limit the editor to only open one instance per file, then this PR is pretty much moot, since we would need to keep all windows in one instance to keep track of the opened files. Instead, we'd need to define all the variables and actions on the window level, instead of the application level. I don't know Gtk, but I guess changing the base class might be half the fix.

I'd like try setting up the dev environment again and look into this more, but I already know that I won't have the time for that this weekend either. Since we won't wanna take the approach in this PR, I'd be fine with closing it in case anyone else wants to pick this up. If the issue is still open whenever I figure out where I went wrong in the setup guide I can still come back to it.

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.

Running two instances of Policy Editor (GUI) creates shared/conflicting state

3 participants