You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@geode.apache.org by GitBox <gi...@apache.org> on 2020/11/30 20:30:26 UTC

[GitHub] [geode] kirklund commented on a change in pull request #5778: GEODE-7739: Address race condition in FederatingManager during listener creation

kirklund commented on a change in pull request #5778:
URL: https://github.com/apache/geode/pull/5778#discussion_r532882325



##########
File path: geode-core/src/main/java/org/apache/geode/management/internal/ManagementCacheListener.java
##########
@@ -109,8 +108,15 @@ public void afterUpdate(EntryEvent<String, Object> event) {
 
   }
 
-  void markReady() {
-    readyForEvents = true;
+  private void blockUntilReady() {
+    try {
+      readyForEvents.await();
+    } catch (InterruptedException e) {
+      // ignored

Review comment:
       Anytime you catch an InterruptedException, you should reset the interrupt bit unless the thread is locally owned and it will actually terminate when interrupted:
   ```
   try {
     readyForEvents.await();
   } catch (InterruptedException e) {
     Thread.interrupt();
     // recommended: throw new RunnableException(e); -- use an appropriate GemFire exception here
   }
   ```
   @upthewaterspout wrote an article but about this but I'm not sure where it is.

##########
File path: geode-core/src/main/java/org/apache/geode/management/internal/NotificationCacheListener.java
##########
@@ -15,100 +15,47 @@
 package org.apache.geode.management.internal;
 
 
+import java.util.concurrent.CountDownLatch;
+
 import javax.management.Notification;
 
-import org.apache.geode.cache.CacheListener;
 import org.apache.geode.cache.EntryEvent;
-import org.apache.geode.cache.RegionEvent;
+import org.apache.geode.cache.util.CacheListenerAdapter;
 
 /**
  * This listener will be attached to each notification region corresponding to a member
- *
  */
-public class NotificationCacheListener implements CacheListener<NotificationKey, Notification> {
-
-  /**
-   * For the
-   */
-  private NotificationHubClient notifClient;
+public class NotificationCacheListener extends CacheListenerAdapter<NotificationKey, Notification> {
 
-  private volatile boolean readyForEvents;
+  private final NotificationHubClient notifClient;
+  private final CountDownLatch readyForEvents;
 
   public NotificationCacheListener(MBeanProxyFactory proxyHelper) {
-
     notifClient = new NotificationHubClient(proxyHelper);
-    this.readyForEvents = false;
-
+    this.readyForEvents = new CountDownLatch(1);
   }
 
   @Override
   public void afterCreate(EntryEvent<NotificationKey, Notification> event) {
-    if (!readyForEvents) {
-      return;
-    }
+    blockUntilReady();
     notifClient.sendNotification(event);
-
-  }
-
-  @Override
-  public void afterDestroy(EntryEvent<NotificationKey, Notification> event) {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void afterInvalidate(EntryEvent<NotificationKey, Notification> event) {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void afterRegionClear(RegionEvent<NotificationKey, Notification> event) {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void afterRegionCreate(RegionEvent<NotificationKey, Notification> event) {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void afterRegionDestroy(RegionEvent<NotificationKey, Notification> event) {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void afterRegionInvalidate(RegionEvent<NotificationKey, Notification> event) {
-    // TODO Auto-generated method stub
-
-  }
-
-  @Override
-  public void afterRegionLive(RegionEvent<NotificationKey, Notification> event) {
-    // TODO Auto-generated method stub
-
   }
 
   @Override
   public void afterUpdate(EntryEvent<NotificationKey, Notification> event) {
-    if (!readyForEvents) {
-      return;
-    }
+    blockUntilReady();
     notifClient.sendNotification(event);
-
   }
 
-  @Override
-  public void close() {
-    // TODO Auto-generated method stub
-
+  private void blockUntilReady() {
+    try {
+      readyForEvents.await();

Review comment:
       Same problems as described for ManagementCacheListener apply here.

##########
File path: geode-core/src/main/java/org/apache/geode/management/internal/ManagementCacheListener.java
##########
@@ -109,8 +108,15 @@ public void afterUpdate(EntryEvent<String, Object> event) {
 
   }
 
-  void markReady() {
-    readyForEvents = true;
+  private void blockUntilReady() {
+    try {
+      readyForEvents.await();
+    } catch (InterruptedException e) {
+      // ignored

Review comment:
       Also: If you don't rethrow the InterruptedException within a runtime exception, then this code probably needs to perform some sort of loop that checks a CancelCriterion. Grepping 'catch (InterruptedException' on the Geode product code (not tests) should give some good examples.

##########
File path: geode-core/src/main/java/org/apache/geode/management/internal/ManagementCacheListener.java
##########
@@ -33,20 +35,18 @@
 
   private static final Logger logger = LogService.getLogger();
 
-  private MBeanProxyFactory proxyHelper;
+  private final MBeanProxyFactory proxyHelper;
 
-  private volatile boolean readyForEvents;
+  private final CountDownLatch readyForEvents;

Review comment:
       The latch should probably be an instance of StoppableCountDownLatch so that it will abort (by throwing) if the cache is closed while threads are waiting on the latch. Otherwise, this has the potential to hang.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org