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

Multiple race conditions when saving files #1539

Closed
p-e-w opened this issue Feb 26, 2020 · 1 comment
Closed

Multiple race conditions when saving files #1539

p-e-w opened this issue Feb 26, 2020 · 1 comment

Comments

@p-e-w
Copy link
Contributor

p-e-w commented Feb 26, 2020

Description of the problem or steps to reproduce

As far as I can tell, there is currently no locking at all when saving/loading files. This sets the stage for several potentially dangerous race conditions:

  • If a plugin calls Buffer.Save() from an separate goroutine (e.g. a timer or a background job), this save might interleave with a user-initiated save operation, corrupting the file.

  • Buffer.ReOpen() can also interleave with Buffer.Save(), loading the file in a partially written state.

  • Buffer.Backup() is called asynchronously every 8 seconds (while the buffer is being modified). This means that if creating the backup takes longer than 8 seconds (e.g. slow network mount), the writes will also interleave and potentially corrupt the backup.

There might be more, this is just what I noticed from a quick look through the code.

Specifications

Commit hash: 2ef4f83
OS: Fedora 31
Terminal: GNOME Terminal

zyedidia added a commit that referenced this issue Jun 22, 2020
This commit introduces several improvements to the backup system.

* Backups are made every 8 seconds for buffers that have been modified
  since the last backup.

* The `permbackup` option allows users to specify that backups should
  be kept permanently.

* `The backupdir` option allows users to store backups in a custom
   directory.

Fixes #1641
Fixes #1536
Ref #1539 (removes possibility of race condition for backups)
@zyedidia
Copy link
Owner

It is not possible for a plugin background job to interleave with Save because background job callbacks are run on the same thread as the main micro thread. For example when the job produces stdout, micro schedules the onStdout callback to be called on the main thread by placing the callback on the jobs channel.

In the case where the plugin spawns and manages its own goroutine (I'm not even sure if this is possible), I have just added a commit which adds a lock (micro.Lock:Lock() and micro.Lock:Unlock()) for plugins to use to make sure they don't interfere with any event handling (the lock is held by micro during all event handling code). This lock should only be used when a plugin is performing operations on the micro core in a plugin-managed thread/goroutine.

dmaluka added a commit to dmaluka/micro that referenced this issue Sep 30, 2023
The lock provided to lua as micro.Lock does not really work: an attempt
to use it via micro.Lock:Lock() results in an error:

Plugin initlua: init:260: attempt to call a non-function object
stack traceback:
	init:260: in main chunk
	[G]: ?

The reason is that the value that is provided to lua is a copy of the
mutex, not the mutex itself.

Ref zyedidia#1539
zyedidia pushed a commit that referenced this issue Oct 16, 2023
The lock provided to lua as micro.Lock does not really work: an attempt
to use it via micro.Lock:Lock() results in an error:

Plugin initlua: init:260: attempt to call a non-function object
stack traceback:
	init:260: in main chunk
	[G]: ?

The reason is that the value that is provided to lua is a copy of the
mutex, not the mutex itself.

Ref #1539
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

No branches or pull requests

2 participants