unison-fsmonitor icon indicating copy to clipboard operation
unison-fsmonitor copied to clipboard

Race condition can leave files out of sync while syncing between local dirs

Open comex opened this issue 2 years ago • 2 comments

To reproduce (I'm on macOS 12.3.1):

mkdir /tmp/a /tmp/b
unison /tmp/a /tmp/b -repeat watch -ui text -debug fswatch+

While this is running, try

echo $RANDOM > /tmp/a/x

I see a bunch of output, quoted below. Importantly, there is a delay between "Synchronization complete" being printed and new WAIT commands being sent. If you modify /tmp/a/x again during this interval, a second synchronization does not occur, and so /tmp/a/x and /tmp/b/x stay out of sync (until one of them is changed yet again or Unison is restarted).

I can reproduce this on Unison 2.51.5 as well as the latest master at time of writing. It doesn't occur when using Unison's built-in fsmonitor implementation on Linux.

The cause appears to be the timing of CHANGES responses. This fsmonitor implementation sends CHANGES immediately as soon as changes occur. But the built-in fsmonitor has more of a polling model, where CHANGES responses are sent only in response to WAIT commands; a CHANGE response terminates a wait, and changes that occur while not waiting should be reported at the next wait. In fact, Unison itself seems to ignore the arguments to CHANGES responses; it simply uses CHANGES as a notification that it should terminate the wait and send its own CHANGES command to request filenames of the files that changed. (Nevertheless, the built-in fsmonitor does include the hashes of changed files in its CHANGES response; there can be multiple hashes in a single response.)

Edit: To further clarify: WAIT is like select(), terminated by a CHANGES response, and CHANGES commands are like read(). They affect the same state (list of pending changes). I think.

[fswatch+] >> CHANGES d03c239c5bae8b7a9a35a6284d8a9512
Looking for changes
[fswatch+] << CHANGES d03c239c5bae8b7a9a35a6284d8a9512
[fswatch+] >> RECURSIVE x
[fswatch+] >> DONE
[fswatch+] << START d03c239c5bae8b7a9a35a6284d8a9512 /private/tmp/a x
[fswatch+] >> OK
[fswatch+] << DONE
[fswatch+] << CHANGES ee6f81089ac5b4e616740c34d688212d
[fswatch+] >> RECURSIVE x
[fswatch+] >> RECURSIVE %2Eunison%2Ex%2Eee6f81089ac5b4e616740c34d688212d%2Eunison%2Etmp
[fswatch+] >> DONE
[fswatch+] << START ee6f81089ac5b4e616740c34d688212d /private/tmp/b x
[fswatch+] >> OK
[fswatch+] << DONE
Reconciling changes
changed  ---->            x  
a            : changed file       modified on 2022-05-09 at 19:05:43  size 6         rw-r--r--
b            : unchanged file     modified on 2022-05-09 at 19:05:39  size 6         rw-r--r--
Propagating updates
Unison 2.51.5 (ocaml 4.12.1) started propagating changes at 19:05:44.67 on 09 May 2022
[BGN] Updating file x from /private/tmp/a to /private/tmp/b
[END] Updating file x
Unison 2.51.5 (ocaml 4.12.1) finished propagating changes at 19:05:44.67 on 09 May 2022, 0.001 s
Saving synchronizer state
Synchronization complete at 19:05:44  (1 item transferred, 0 skipped, 0 failed)
[fswatch+] >> CHANGES ee6f81089ac5b4e616740c34d688212d
[fswatch+] >> CHANGES ee6f81089ac5b4e616740c34d688212d
[fswatch+] >> CHANGES ee6f81089ac5b4e616740c34d688212d
[fswatch+] << WAIT d03c239c5bae8b7a9a35a6284d8a9512
[fswatch+] << WAIT ee6f81089ac5b4e616740c34d688212d

comex avatar May 10 '22 02:05 comex

Thank you very much for reporting! Will have a closer look as soon as I can.

autozimu avatar May 16 '22 21:05 autozimu

Has there been any updates on this issue? I want to use this with unison to sync two local directories on my MacBook but am hesitant to try because this issue is still open.

Either way, thank you for all of your work on this. Much appreciated.

chrisblossom avatar Dec 02 '23 05:12 chrisblossom