public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
From: Jon Turney <jon.turney@dronecode.org.uk>
To: Cygwin Patches <cygwin-patches@cygwin.com>
Subject: Re: [PATCH 08/11] Cygwin: testsuite: Busy-wait in cancel3 and cancel5
Date: Mon, 17 Jul 2023 12:51:36 +0100	[thread overview]
Message-ID: <8a504ebe-9ce0-867a-f1a3-f38411129019@dronecode.org.uk> (raw)
In-Reply-To: <5aa21952-a13d-f304-8b63-18ee4885c308@dronecode.org.uk>

[-- Attachment #1: Type: text/plain, Size: 2285 bytes --]

On 14/07/2023 14:04, Jon Turney wrote:
> On 13/07/2023 19:53, Corinna Vinschen wrote:
>>>>> normally after 10 seconds. (See the commentary in pthread::cancel() in
>>>>> thread.cc, where it checks if the target thread is inside the kernel,
>>>>> and silently converts the cancellation into a deferred one)
>>>>
>>>> Nevertheless, I think this is ok to do.  The description of 
>>>> pthread_cancel
>>>> contains this:
>>>>
>>>>    Asynchronous cancelability means that the thread can be canceled at
>>>>    any time (usually immediately, but the system does not guarantee 
>>>> this).
>>>>
>>>> And
>>>>
>>>>    The above steps happen asynchronously with respect to the
>>>>    pthread_cancel() call; the return status of pthread_cancel() merely
>>>>    informs the caller whether the cancellation request was successfully
>>>>    queued.
>>>>
>>>> So any assumption *when* the cancallation takes place is may be wrong.
> 
> Yeah.
> 
> I think the flakiness is when we happen to try to async cancel while in 
> the Windows kernel, which implicitly converts to a deferred 
> cancellation, but there are no cancellation points in the the thread, so 
> it arrives at pthread_exit() and returns a exit code other than 
> PTHREAD_CANCELED.
> 
> I did consider making the test non-flaky by adding a final call to 
> pthread_testcancel(), to notice any failed async cancellation which has 
> been converted to a deferred one.
> 
> But then that is just the same as the deferred cancellation tests, and 
> confirms the cancellation happens, but not that it's async, which is 
> part of the point of the test.
> 
> I guess this could also check that not all of the threads ran for all 10 
> seconds, which would indicate that at least some of them were cancelled 
> asynchronously.

I wrote this, attached, which does indeed make this test more reliable.

You point is well made that this is making assumptions about how quickly 
async cancellation works that are not required by the standard

(It would be a valid, if strange implementation, if async cancellation 
always took 10 seconds to take effect, which this test assumes isn't the 
case)

Perhaps there is a better way to write a test that async cancellation 
works in the absence of cancellation points, but it eludes me...

[-- Attachment #2: 0001-Cygwin-testsuite-Make-cancel3-and-cancel5-more-robus.patch --]
[-- Type: text/plain, Size: 2819 bytes --]

From d0023fa3ea1e8f29e80d473ab13d8200bdd2dc3a Mon Sep 17 00:00:00 2001
From: Jon Turney <jon.turney@dronecode.org.uk>
Date: Sat, 15 Jul 2023 17:57:43 +0100
Subject: [PATCH] Cygwin: testsuite: Make cancel3 and cancel5 more robust

Despite our efforts, sometimes the async cancellation gets deferred.

Notice this by calling pthread_testcancel(), and then try to work out if
async cancellation was ever successful by checking if all threads ran
for the full 10 seconds, or if some were stopped early.
---
 winsup/testsuite/winsup.api/pthread/cancel3.c | 16 +++++++++++++++-
 winsup/testsuite/winsup.api/pthread/cancel5.c | 14 ++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/winsup/testsuite/winsup.api/pthread/cancel3.c b/winsup/testsuite/winsup.api/pthread/cancel3.c
index 07feb7c9b..075f052cc 100644
--- a/winsup/testsuite/winsup.api/pthread/cancel3.c
+++ b/winsup/testsuite/winsup.api/pthread/cancel3.c
@@ -92,6 +92,9 @@ mythread(void * arg)
 	}
     }
 
+  /* Notice if asynchronous cancel got deferred */
+  pthread_testcancel();
+
   return result;
 }
 
@@ -101,6 +104,7 @@ main()
   int failed = 0;
   int i;
   pthread_t t[NUMTHREADS + 1];
+  int ran_to_completion = 0;
 
   assert((t[0] = pthread_self()) != NULL);
 
@@ -130,7 +134,7 @@ main()
    * Standard check that all threads started.
    */
   for (i = 1; i <= NUMTHREADS; i++)
-    { 
+    {
       if (!threadbag[i].started)
 	{
 	  failed |= !threadbag[i].started;
@@ -166,9 +170,19 @@ main()
 		  threadbag[i].count,
 		  result);
 	}
+
+      if (threadbag[i].count >= 10)
+	ran_to_completion++;
+
       failed = (failed || fail);
     }
 
+  if (ran_to_completion >= 10)
+    {
+      fprintf(stderr, "All threads ran to completion, async cancellation never happened\n");
+      failed = TRUE;
+    }
+
   assert(!failed);
 
   /*
diff --git a/winsup/testsuite/winsup.api/pthread/cancel5.c b/winsup/testsuite/winsup.api/pthread/cancel5.c
index 999b3c95c..23c02afe4 100644
--- a/winsup/testsuite/winsup.api/pthread/cancel5.c
+++ b/winsup/testsuite/winsup.api/pthread/cancel5.c
@@ -93,6 +93,9 @@ mythread(void * arg)
 	}
     }
 
+  /* Notice if asynchronous cancel got deferred */
+  pthread_testcancel();
+
   return result;
 }
 
@@ -102,6 +105,7 @@ main()
   int failed = 0;
   int i;
   pthread_t t[NUMTHREADS + 1];
+  int ran_to_completion = 0;
 
   for (i = 1; i <= NUMTHREADS; i++)
     {
@@ -165,9 +169,19 @@ main()
 		  threadbag[i].count,
 		  result);
 	}
+
+      if (threadbag[i].count >= 10)
+       ran_to_completion++;
+
       failed = (failed || fail);
     }
 
+  if (ran_to_completion >= 10)
+    {
+      fprintf(stderr, "All threads ran to completion, async cancellation never happened\n");
+      failed = TRUE;
+    }
+
   assert(!failed);
 
   /*
-- 
2.39.0


  parent reply	other threads:[~2023-07-17 11:51 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-13 11:38 [PATCH 00/11] More testsuite fixes Jon Turney
2023-07-13 11:38 ` [PATCH 01/11] Cygwin: testsuite: Setup test prereqs in 'installation' the tests run in Jon Turney
2023-07-13 11:38 ` [PATCH 02/11] Cygwin: testsuite: Add a simple timeout mechanism Jon Turney
2023-07-13 11:38 ` [PATCH 03/11] Cygwin: testsuite: Remove const from writable string in fcntl07b Jon Turney
2023-07-13 11:38 ` [PATCH 04/11] Cygwin: testsuite: Skip devdsp test when no audio devices present Jon Turney
2023-07-13 11:38 ` [PATCH 05/11] Cygwin: testsuite: Just log result of second open of /dev/dsp Jon Turney
2023-07-13 11:38 ` [PATCH 06/11] Cygwin: testsuite: Also check direct call in systemcall Jon Turney
2023-07-13 11:39 ` [PATCH 07/11] Cygwin: testsuite: Fix for limited thread priority values Jon Turney
2023-07-13 11:39 ` [PATCH 08/11] Cygwin: testsuite: Busy-wait in cancel3 and cancel5 Jon Turney
2023-07-13 11:43   ` Jon Turney
2023-07-13 18:16   ` Corinna Vinschen
2023-07-13 18:37     ` Corinna Vinschen
2023-07-13 18:53       ` Corinna Vinschen
2023-07-14 13:04         ` Jon Turney
2023-07-14 18:57           ` Corinna Vinschen
2023-07-17 11:05             ` Corinna Vinschen
2023-07-17 11:51               ` Jon Turney
2023-07-17 14:21                 ` Corinna Vinschen
2023-07-17 15:41                   ` Corinna Vinschen
2023-07-17 18:23                     ` Corinna Vinschen
2023-07-18 11:20                     ` Jon Turney
2023-07-18 12:09                       ` Corinna Vinschen
2023-07-18 15:52                         ` Jon Turney
2023-07-17 11:51           ` Jon Turney [this message]
2023-07-17 14:04             ` Corinna Vinschen
2023-07-17 14:22               ` Corinna Vinschen
2023-07-13 11:39 ` [PATCH 09/11] Cygwin: testsuite: Fix a buffer overflow in symlink01 Jon Turney
2023-07-13 18:17   ` Corinna Vinschen
2023-07-14 13:04     ` Jon Turney
2023-07-13 11:39 ` [PATCH 10/11] Cygwin: testsuite: Minor fixes to umask03 Jon Turney
2023-07-13 18:18   ` Corinna Vinschen
2023-07-13 11:39 ` [PATCH 11/11] Cygwin: testsuite: Drop Adminstrator privileges while running tests Jon Turney
2023-07-13 18:05 ` [PATCH 00/11] More testsuite fixes Corinna Vinschen
2023-07-17 11:58 ` Jon Turney
2023-07-17 14:02   ` Corinna Vinschen
2023-07-18 13:37     ` Jon Turney
2023-07-18 14:52       ` Corinna Vinschen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8a504ebe-9ce0-867a-f1a3-f38411129019@dronecode.org.uk \
    --to=jon.turney@dronecode.org.uk \
    --cc=cygwin-patches@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).