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
       }

Reply via email to