Fixed Signal crash on Ubuntu 20.04 27/257927/4
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Thu, 6 May 2021 11:49:20 +0000 (12:49 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Thu, 6 May 2021 12:51:21 +0000 (13:51 +0100)
Change-Id: I785ed3bf0142ba6adb4bbc3484a0e0a36a2b7f53

automated-tests/src/common/signal-helper.h
automated-tests/src/dali/utc-Dali-SignalTemplates.cpp
dali/public-api/signals/base-signal.cpp
dali/public-api/signals/base-signal.h

index 84844cf..4084e28 100644 (file)
@@ -2,7 +2,7 @@
 #define SIGNAL_HELPER
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -720,6 +720,12 @@ public:
     signal.Connect(this, &TestEmitDuringCallback::DeleteSignalDuringEmit);
   }
 
+  void DeleteDuringEmitConnect(TestSignals::FloatRet0ParamSignal& signal)
+  {
+    mFloatRet0ParamSignal = &signal;
+    signal.Connect(this, &TestEmitDuringCallback::DeleteRetSignalDuringEmit);
+  }
+
   void VoidSlotVoid()
   {
     // Emitting during Emit is very bad!
@@ -733,6 +739,13 @@ public:
     delete mVoidSignalVoid;
   }
 
+  float DeleteRetSignalDuringEmit()
+  {
+    // deleting the signal during the emit
+    delete mFloatRet0ParamSignal;
+    return 0.0f;
+  }
+
   float FloatRet0Param()
   {
     // Emitting during Emit is very bad!
index d3a03fc..67299e2 100644 (file)
@@ -1621,13 +1621,25 @@ int UtcDaliSignalDeleteDuringEmit(void)
 
   TestApplication application; // Create core for debug logging
 
-  TestSignals::VoidRetNoParamSignal* signal = new TestSignals::VoidRetNoParamSignal;
+  {
+    TestSignals::VoidRetNoParamSignal* signal = new TestSignals::VoidRetNoParamSignal;
 
-  TestEmitDuringCallback handler1;
-  handler1.DeleteDuringEmitConnect(*signal);
+    TestEmitDuringCallback handler1;
+    handler1.DeleteDuringEmitConnect(*signal);
 
-  // should just log an error
-  signal->Emit();
+    // should just log an error
+    signal->Emit();
+  }
+
+  {
+    TestSignals::FloatRet0ParamSignal* signal = new TestSignals::FloatRet0ParamSignal;
+
+    TestEmitDuringCallback handler1;
+    handler1.DeleteDuringEmitConnect(*signal);
+
+    // should just log an error
+    signal->Emit();
+  }
 
   tet_result(TET_PASS);
 
index 9b24091..a8c55ad 100644 (file)
@@ -43,6 +43,12 @@ BaseSignal::~BaseSignal()
   if(mEmittingFlag)
   {
     DALI_LOG_ERROR("Invalid destruction of Signal during Emit()\n");
+
+    // Set the signal deletion flag as well if set
+    if(mSignalDeleted)
+    {
+      *mSignalDeleted = true;
+    }
   }
 
   // The signal is being destroyed. We have to inform any slots
index 1e42e0b..b63e1e2 100644 (file)
@@ -169,6 +169,10 @@ public:
       return returnVal;
     }
 
+    // Guards against calling CleanupConnections if the signal is deleted during emission
+    bool signalDeleted{false};
+    mSignalDeleted = &signalDeleted;
+
     // If more connections are added by callbacks, these are ignore until the next Emit()
     // Note that count cannot be reduced while iterating
     const std::size_t initialCount(mSignalConnections.size());
@@ -185,8 +189,12 @@ public:
       }
     }
 
-    // Cleanup NULL values from Connection container
-    CleanupConnections();
+    if(!signalDeleted)
+    {
+      // Cleanup NULL values from Connection container
+      CleanupConnections();
+      mSignalDeleted = nullptr;
+    }
 
     return returnVal;
   }
@@ -208,6 +216,10 @@ public:
       return;
     }
 
+    // Guards against calling CleanupConnections if the signal is deleted during emission
+    bool signalDeleted{false};
+    mSignalDeleted = &signalDeleted;
+
     // If more connections are added by callbacks, these are ignore until the next Emit()
     // Note that count cannot be reduced while iterating
     const std::size_t initialCount(mSignalConnections.size());
@@ -224,8 +236,12 @@ public:
       }
     }
 
-    // Cleanup NULL values from Connection container
-    CleanupConnections();
+    if(!signalDeleted)
+    {
+      // Cleanup NULL values from Connection container
+      CleanupConnections();
+      mSignalDeleted = nullptr;
+    }
   }
 
   // Connect / Disconnect function for use by Signal implementations
@@ -313,9 +329,10 @@ private:
   BaseSignal& operator=(BaseSignal&&) = delete;      ///< Deleted move assignment operator. @SINCE_1_9.25
 
 private:
-  std::vector<SignalConnection> mSignalConnections;   ///< Array of connections
-  uint32_t                      mNullConnections{0};  ///< Empty Connections in the array.
-  bool                          mEmittingFlag{false}; ///< Used to guard against nested Emit() calls
+  std::vector<SignalConnection> mSignalConnections;      ///< Array of connections
+  uint32_t                      mNullConnections{0};     ///< Empty Connections in the array.
+  bool                          mEmittingFlag{false};    ///< Used to guard against nested Emit() calls.
+  bool*                         mSignalDeleted{nullptr}; ///< Used to guard against deletion during Emit() calls.
 };
 
 /**