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

[undo] can't undo some threaded commands #2266

Closed
midichef opened this issue Jan 23, 2024 · 2 comments · Fixed by #2345
Closed

[undo] can't undo some threaded commands #2266

midichef opened this issue Jan 23, 2024 · 2 comments · Fixed by #2345
Labels

Comments

@midichef
Copy link
Contributor

Small description
After a pasting into cells or rows using syspaste-*, undo does not restore the original value of the cell.

Steps to reproduce with sample data and a .vd
Starting with this tsv sheet:

cells
first
second

hit zY on the cell that contains"first", then j and then zP

cells
first
first

then hit U, and no undo happens. Instead there is a message: nothing to undo on current sheet.

To trigger the bug, syspaste-cells must be done manually. If it's done inside -p script.vdj, then undo-last works as expected.

Additional context
saul.pw/VisiData v3.1dev

The behavior started with a9e4e05 and its parent commit.

I've looked into the undo code a bit. The problem is that when syspaste-* runs addUndo(), vd.activeCommand is None, so the function returns without adding to r.undofuncs. I'm not sure what the fix should be.

@midichef midichef added the bug label Jan 23, 2024
@midichef
Copy link
Contributor Author

midichef commented Feb 1, 2024

The problem is a race condition in basesheet.py:

escaped = super().execCommand2(cmd, vdglobals=vdglobals)

vd.callNoExceptions(vd.cmdlog.afterExecSheet, vd.activeSheet, escaped, err)

The events happen in this order:

  1. execCommand() runs execCommand2(), which starts pasteFromClipboard() in its own thread.

  2. pasteFromClipboard() starts. It will eventually look at vd.activeCommand, but not yet. It runs a command to check the clipboard, but that takes a while to finish, so it is paused.

  3. execCommand() resumes. It runs afterExecSheet() which changes vd.activeCommand to None.

  4. pasteFromClipboard() resumes. When it tries to make its undo functions, in addUndo(), it sees the wrong new value of vd.activeCommand, so it does not add its undo functions to the command log sheet.

  5. Because there are no undo functions, when I do undo-last, it fails.

As a confirmation that this is what's happening, undo is fixed when I remove the @asyncthread decorator from pasteFromClipboard().

A fix would be to make sure afterExecSheet() doesn't run until the threaded command finishes. But at the moment I'm not sure how to do that.

@midichef midichef changed the title [undo] can't undo syspaste [undo] can't undo some threaded commands Feb 1, 2024
midichef added a commit to midichef/visidata that referenced this issue Feb 4, 2024
Use a temporary workaround for the bug in saulpw#2266, to allow undo
during testing of sort-selected-asc and sort-selected-desc.
Use assertions to ensure no sheet data is lost.
@midichef
Copy link
Contributor Author

A fix would be to make sure afterExecSheet() doesn't run until the threaded command finishes. But at the moment I'm not sure how to do that.

On looking into this deeper, I realized such a fix was not workable.

There's a better way to fix this. Instead of having only 1 activeCommand for all the threads, give each thread its own activeCommand. I'll submit a PR for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant