This is an automated email from the ASF dual-hosted git repository. bschuchardt pushed a commit to branch feature/GEODE-7220 in repository https://gitbox.apache.org/repos/asf/geode.git
commit 5ea8f56a7e167184b465fdb8d249522e1e33b214 Author: Bruce Schuchardt <bschucha...@pivotal.io> AuthorDate: Thu Sep 19 15:31:13 2019 -0700 GEODE-7220 NPE in the logs on reconnect Use reflection to poke a new Receiver into JGroups to avoid synchronization problems in JGroups code. No new tests were needed. --- .../membership/gms/messenger/GMSQuorumChecker.java | 3 +-- .../membership/gms/messenger/JGroupsMessenger.java | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/GMSQuorumChecker.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/GMSQuorumChecker.java index 9a09366..3a5d716 100644 --- a/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/GMSQuorumChecker.java +++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/GMSQuorumChecker.java @@ -114,8 +114,7 @@ public class GMSQuorumChecker { public void resume() { - channel.setReceiver(null); - channel.setReceiver(new QuorumCheckerReceiver()); + JGroupsMessenger.setChannelReceiver(channel, new QuorumCheckerReceiver()); } diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java index 837f461..678d4c0 100644 --- a/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java +++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java @@ -49,11 +49,13 @@ import java.util.stream.Collectors; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.apache.logging.log4j.Logger; import org.jgroups.Address; +import org.jgroups.Channel; import org.jgroups.Event; import org.jgroups.JChannel; import org.jgroups.Message; import org.jgroups.Message.Flag; import org.jgroups.Message.TransientFlag; +import org.jgroups.Receiver; import org.jgroups.ReceiverAdapter; import org.jgroups.View; import org.jgroups.ViewId; @@ -69,6 +71,7 @@ import org.apache.geode.ForcedDisconnectException; import org.apache.geode.GemFireConfigException; import org.apache.geode.GemFireIOException; import org.apache.geode.InternalGemFireError; +import org.apache.geode.InternalGemFireException; import org.apache.geode.SystemConnectException; import org.apache.geode.annotations.internal.MutableForTesting; import org.apache.geode.distributed.DistributedSystemDisconnectedException; @@ -179,6 +182,19 @@ public class JGroupsMessenger implements Messenger { */ private JGroupsReceiver jgroupsReceiver; + public static void setChannelReceiver(JChannel channel, Receiver r) { + try { + // Channel.setReceiver() won't set a new receiver unless the field is null but that + // causes NPEs in receiver threads because use of the the field isn't synchronized. + // Attempt to use reflection to avoid having the field be null. See GEODE-7220 + Field receiver = Channel.class.getDeclaredField("receiver"); + receiver.setAccessible(true); + receiver.set(channel, r); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new InternalGemFireException("unable to establish a JGroups receiver", e); + } + } + @Override @edu.umd.cs.findbugs.annotations.SuppressWarnings( value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD") @@ -358,9 +374,8 @@ public class JGroupsMessenger implements Messenger { nackack2HeaderId = ClassConfigurator.getProtocolId(NAKACK2.class); try { - myChannel.setReceiver(null); jgroupsReceiver = new JGroupsReceiver(); - myChannel.setReceiver(jgroupsReceiver); + setChannelReceiver(myChannel, jgroupsReceiver); if (!reconnecting) { myChannel.connect("AG"); // Apache Geode }