Code

Added debian/patches/perl_deadlock.dpatch.
[pkg-collectd.git] / debian / patches / perl_deadlock.dpatch
1 #! /bin/sh /usr/share/dpatch/dpatch-run
2 ## perl_deadlock.dpatch by Sebastian Harl <sh@tokkee.org>
3 ##
4 ## DP: Collectd.pm: Improved the way access to @plugins is synchronized.
5 ## DP:
6 ## DP: So far, a lock has been placed on @plugins, so that no two threads could
7 ## DP: access the list of plugins simultaneously. This could cause problems
8 ## DP: which in certain situations could even lead to deadlocks. E.g. when
9 ## DP: using the perl plugin in combination with the rrdtool plugin with
10 ## DP: debugging enabled one would get hit by the following situation: the perl
11 ## DP: plugin holds the lock on @plugins and then dispatches values to the
12 ## DP: rrdtool plugin from some Perl plugin's read function. The rrdtool plugin
13 ## DP: then tries to acquire its cache lock. At the same time some other plugin
14 ## DP: dispatches values to the rrdtool plugin as well and this thread now
15 ## DP: holds the lock on the rrdtool cache. While holding that lock, the
16 ## DP: rrdtool plugin might dispatch a debug logging message and thus calls the
17 ## DP: perl plugin's log-callback which tries to get the lock on @plugins thus
18 ## DP: causing a deadlock.
19 ## DP:
20 ## DP: This has been resolved by the following two changes:
21 ## DP:
22 ## DP:  * Restrict the lock to the list of plugins of one type. This allows to
23 ## DP:    access e.g. read and log plugins in parallel.
24 ## DP:
25 ## DP:  * Unlock the variable before calling the Perl callback function. This
26 ## DP:    further prevents nested locks.
27 ## DP:
28 ## DP: (This is upstream Git commit dffb71cd6668e98f93c12da2ee2bd7a728d7292a)
30 @DPATCH@
32 diff a/bindings/perl/Collectd.pm b/bindings/perl/Collectd.pm
33 --- a/bindings/perl/Collectd.pm
34 +++ b/bindings/perl/Collectd.pm
35 @@ -133,6 +133,8 @@ sub DEBUG   { _log (scalar caller, LOG_DEBUG,   shift); }
36  sub plugin_call_all {
37         my $type = shift;
38  
39 +       my %plugins;
40 +
41         our $cb_name = undef;
42  
43         if (! defined $type) {
44 @@ -148,9 +150,13 @@ sub plugin_call_all {
45                 return;
46         }
47  
48 -       lock @plugins;
49 -       foreach my $plugin (keys %{$plugins[$type]}) {
50 -               my $p = $plugins[$type]->{$plugin};
51 +       {
52 +               lock %{$plugins[$type]};
53 +               %plugins = %{$plugins[$type]};
54 +       }
55 +
56 +       foreach my $plugin (keys %plugins) {
57 +               my $p = $plugins{$plugin};
58  
59                 my $status = 0;
60  
61 @@ -261,7 +267,7 @@ sub plugin_register {
62                         cb_name   => $data,
63                 );
64  
65 -               lock @plugins;
66 +               lock %{$plugins[$type]};
67                 $plugins[$type]->{$name} = \%p;
68         }
69         else {
70 @@ -286,7 +292,7 @@ sub plugin_unregister {
71                 return plugin_unregister_data_set ($name);
72         }
73         elsif (defined $plugins[$type]) {
74 -               lock @plugins;
75 +               lock %{$plugins[$type]};
76                 delete $plugins[$type]->{$name};
77         }
78         else {