The previous patch that we had, to use a temporary file, is useful: it prevents the situation where a half-written file is present on disk under the name that the readers expect. For example, this solves the scenario where the write is interrupted, and then the build process is restarted and something reads the partially written file. This could happen when using intltool-merge during development. Nevertheless, the existing patch doesn't actually solve the problem of concurrent writes: the name of the temporary file is fixed, so if two writers attempt to write the file, they may open the same temporary file and then finally rename the temporary file to destination. Readers will then read a corrupted file. This happens in https://bugzilla.redhat.com/show_bug.cgi?id=2268342, where we get a message that indicates the cache file is corrupted ("odd number of elements"), and a desktop file with some missing translations is written. Patch was verified by rebuilding xfce4-terminal 10 times with an inserted check that the two desktop files contain the expected number of elements. The patch was written by Bernhard Wiedemann and is available in the intltool repo on launchpad (but misattributed).
46 lines
1.2 KiB
Diff
46 lines
1.2 KiB
Diff
From 7355bdbca18c95a2b99cb254434ad2c2248d6747 Mon Sep 17 00:00:00 2001
|
|
From: Gianfranco Costamagna <locutusofborg@debian.org>
|
|
Date: Wed, 2 Dec 2020 16:52:53 +0100
|
|
Subject: [PATCH] [PATCH] Avoid a race where some processes try to use a
|
|
partial cache
|
|
|
|
Gbp-Pq: 0001-Avoid-a-race-where-some-processes-try-to-use-a-parti.patch.
|
|
---
|
|
intltool-merge.in | 5 +++++
|
|
1 file changed, 5 insertions(+)
|
|
|
|
diff --git a/intltool-merge.in b/intltool-merge.in
|
|
index 05db7cf930..89923a7da1 100644
|
|
--- a/intltool-merge.in
|
|
+++ b/intltool-merge.in
|
|
@@ -43,6 +43,7 @@ use Getopt::Long;
|
|
use Text::Wrap;
|
|
use File::Basename;
|
|
use Encode;
|
|
+use Fcntl qw(:flock);
|
|
|
|
my $must_end_tag = -1;
|
|
my $last_depth = -1;
|
|
@@ -392,11 +393,14 @@ sub load_cache
|
|
|
|
sub get_cached_translation_database
|
|
{
|
|
+ open(my $lockfh, ">", "$cache_file.lock") or die $!;
|
|
+ flock($lockfh, LOCK_EX) or die "Could not lock '$cache_file.lock' - $!";
|
|
my $cache_file_age = -M $cache_file;
|
|
if (defined $cache_file_age)
|
|
{
|
|
if ($cache_file_age <= &get_newest_po_age)
|
|
{
|
|
+ close($lockfh);
|
|
&load_cache;
|
|
return;
|
|
}
|
|
@@ -404,6 +408,7 @@ sub get_cached_translation_database
|
|
}
|
|
|
|
&create_cache;
|
|
+ close($lockfh);
|
|
}
|
|
|
|
sub add_translation
|