Skip to content

PO files may be silently read partially if modified in the middle of reading #894

@HadrienG2

Description

@HadrienG2

I am experimenting with an inotify-based workflow in which updates to source files automatically lead to an update of the .pot template, which then propagate to individual .po files via msgmerge. This is pretty convenient, but there is one issue: for a fully seamless experience, Poedit should handle these background updates when it already has this file opened, allowing me to easily switch between original file editing and translation editing without closing and reopening Poedit constantly.

Poedit actually already partially handles this, but does so imperfectly. If I do remember to save my Poedit changes before working on the original text (which I accept as a technical prerequisite because merging two changesets is complicated), it goes as follows. As the file is updated in the background, Poedit mostly takes care of reloading it automagically. But it will occasionally complain with an error/warning dialog, that is usually harmless but not always, for reasons that I will explain next.

The problem is that Poedit reacts to the first background file write notification that it receives, and does not keep listening to all further change notifications as it reloads the file. As a result, it will often start reloading the partially-written updated PO file before msgmerge is done writing it, and will not reload it again afterwards because it missed the subsequent file update notifications. This will result in Poedit only observing the beginning of the file, not the end of it, which will then result in either PO parsing errors or (much worse) a silent discarding of previous translations that I may not notice. If I proceed to save the PO file in this state, uncommitted translations will be lost, which is bad.

I can think of a few ways in which Poedit could handle this situation better:

  1. Listen to file write notifications in a background thread, and send them to the main thread via some kind of queue as they come. The main thread checks this queue like it would otherwise watch file write notifications, and once it has new entries, it fetches all of them, while ignoring all but the latest update to each file, before taking action. In this way, Poedit can be sure that it always eventually ends up reloading the final version of the file, at the expense of possibly reloading a few non-final versions before that (which may cause errors, that should ideally not be shown to the user right away if more updates to the same file are pending).
    • To avoid crowding a queue with lots of file changes notifications from the same file that will eventually be discarded, a superior concurrent data structure would be some kind of mutex-protected hash-set of files that have been modified, which the main thread swaps with an empty hash set upon readout. But this will require more work on your side as it is a less common way to synchronize threads, and I suspect for typical use cases a queue will work well enough.
  2. Set up a timer based on some reasonable expectations of how long it should take msgmerge to update a file + some desired UX response time criteria like a typical screen frame duration (16.7ms for a 60Hz monitor). When a file write is detected, Poedit start this timer, and only proceeds to reload the file when this duration is elapsed. This will reduce the number of unnecessary reloads, and also decrease the odds that Poedit observes a partially written file. But it may not take the chance of partial write observation to zero if the file is updated unusually slowly for some reason, so some variation of strategy 1 is still needed.
  3. Do not listen to file write notifications at all, instead only listen to notifications about a file being closed after being previously opened for writing. This should more reliably ensure an optimal single-reload behavior than the above option. But it does so at the expense of assuming a "well behaved" file write pattern like that of msgmerge. For example, manual PO file editing using a text editor will not be handled correctly.

What do you think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions