[v2,03/12] test: object-delete: Test deferred delete just before thread stops
diff mbox series

Message ID 20240123011249.22716-4-laurent.pinchart@ideasonboard.com
State Accepted
Headers show
Series
  • libcamera: Hardening against thread race conditions
Related show

Commit Message

Laurent Pinchart Jan. 23, 2024, 1:12 a.m. UTC
The Object::deleteLater() function is expected to not race with stopping
the thread the object is bound to. Add a test for this.

The test currently fails, demonstrating a bug in libcamera.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Fix typo in commit message
---
 test/object-delete.cpp | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

Comments

Milan Zamazal Jan. 23, 2024, 11:53 a.m. UTC | #1
Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes:

> The Object::deleteLater() function is expected to not race with stopping
> the thread the object is bound to. Add a test for this.
>
> The test currently fails, demonstrating a bug in libcamera.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Milan Zamazal <mzamazal@redhat.com>

> ---
> Changes since v1:
>
> - Fix typo in commit message
> ---
>  test/object-delete.cpp | 30 +++++++++++++++++++++++++-----
>  1 file changed, 25 insertions(+), 5 deletions(-)
>
> diff --git a/test/object-delete.cpp b/test/object-delete.cpp
> index eabefe935974..80b7dc41cd37 100644
> --- a/test/object-delete.cpp
> +++ b/test/object-delete.cpp
> @@ -33,10 +33,10 @@ public:
>  	unsigned int *deleteCount_;
>  };
>  
> -class NewThread : public Thread
> +class DeleterThread : public Thread
>  {
>  public:
> -	NewThread(Object *obj)
> +	DeleterThread(Object *obj)
>  		: object_(obj)
>  	{
>  	}
> @@ -63,9 +63,9 @@ protected:
>  		unsigned int count = 0;
>  		TestObject *obj = new TestObject(&count);
>  
> -		NewThread thread(obj);
> -		thread.start();
> -		thread.wait();
> +		DeleterThread delThread(obj);
> +		delThread.start();
> +		delThread.wait();
>  
>  		Thread::current()->dispatchMessages(Message::Type::DeferredDelete);
>  
> @@ -89,6 +89,26 @@ protected:
>  			return TestFail;
>  		}
>  
> +		/*
> +		 * Test that deleteLater() works properly when called just
> +		 * before the object's thread exits.
> +		 */
> +		Thread boundThread;
> +		boundThread.start();
> +
> +		count = 0;
> +		obj = new TestObject(&count);
> +		obj->moveToThread(&boundThread);
> +
> +		obj->deleteLater();
> +		boundThread.exit();
> +		boundThread.wait();
> +
> +		if (count != 1) {
> +			cout << "Object deletion right before thread exit failed (" << count << ")" << endl;
> +			return TestFail;
> +		}
> +
>  		return TestPass;
>  	}
>  };

Patch
diff mbox series

diff --git a/test/object-delete.cpp b/test/object-delete.cpp
index eabefe935974..80b7dc41cd37 100644
--- a/test/object-delete.cpp
+++ b/test/object-delete.cpp
@@ -33,10 +33,10 @@  public:
 	unsigned int *deleteCount_;
 };
 
-class NewThread : public Thread
+class DeleterThread : public Thread
 {
 public:
-	NewThread(Object *obj)
+	DeleterThread(Object *obj)
 		: object_(obj)
 	{
 	}
@@ -63,9 +63,9 @@  protected:
 		unsigned int count = 0;
 		TestObject *obj = new TestObject(&count);
 
-		NewThread thread(obj);
-		thread.start();
-		thread.wait();
+		DeleterThread delThread(obj);
+		delThread.start();
+		delThread.wait();
 
 		Thread::current()->dispatchMessages(Message::Type::DeferredDelete);
 
@@ -89,6 +89,26 @@  protected:
 			return TestFail;
 		}
 
+		/*
+		 * Test that deleteLater() works properly when called just
+		 * before the object's thread exits.
+		 */
+		Thread boundThread;
+		boundThread.start();
+
+		count = 0;
+		obj = new TestObject(&count);
+		obj->moveToThread(&boundThread);
+
+		obj->deleteLater();
+		boundThread.exit();
+		boundThread.wait();
+
+		if (count != 1) {
+			cout << "Object deletion right before thread exit failed (" << count << ")" << endl;
+			return TestFail;
+		}
+
 		return TestPass;
 	}
 };