faulthandler: one more time, fix usage of locks in the watchdog thread

 * Write a new test to ensure that dump_tracebacks_later() still works if
   it was already called and then cancelled before
 * Don't use a variable to check the status of the thread, only rely on locks
 * The thread only releases cancel_event if it was able to acquire it (if
   the timer was interrupted)
 * The main thread always hold this lock. It is only released when
   faulthandler_thread() is interrupted until this thread exits, or at Python
   exit.
diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py
index bfe662e..483c7f1 100644
--- a/Lib/test/test_faulthandler.py
+++ b/Lib/test/test_faulthandler.py
@@ -352,7 +352,7 @@
         with temporary_filename() as filename:
             self.check_dump_traceback_threads(filename)
 
-    def _check_dump_tracebacks_later(self, repeat, cancel, filename):
+    def _check_dump_tracebacks_later(self, repeat, cancel, filename, loops):
         """
         Check how many times the traceback is written in timeout x 2.5 seconds,
         or timeout x 3.5 seconds if cancel is True: 1, 2 or 3 times depending
@@ -364,42 +364,43 @@
 import faulthandler
 import time
 
-def func(repeat, cancel, timeout):
-    if cancel:
+def func(timeout, repeat, cancel, file, loops):
+    for loop in range(loops):
+        faulthandler.dump_tracebacks_later(timeout, repeat=repeat, file=file)
+        if cancel:
+            faulthandler.cancel_dump_tracebacks_later()
+        time.sleep(timeout * 2.5)
         faulthandler.cancel_dump_tracebacks_later()
-    time.sleep(timeout * 2.5)
-    faulthandler.cancel_dump_tracebacks_later()
 
 timeout = {timeout}
 repeat = {repeat}
 cancel = {cancel}
+loops = {loops}
 if {has_filename}:
     file = open({filename}, "wb")
 else:
     file = None
-faulthandler.dump_tracebacks_later(timeout,
-    repeat=repeat, file=file)
-func(repeat, cancel, timeout)
+func(timeout, repeat, cancel, file, loops)
 if file is not None:
     file.close()
 """.strip()
         code = code.format(
-            filename=repr(filename),
-            has_filename=bool(filename),
+            timeout=TIMEOUT,
             repeat=repeat,
             cancel=cancel,
-            timeout=TIMEOUT,
+            loops=loops,
+            has_filename=bool(filename),
+            filename=repr(filename),
         )
         trace, exitcode = self.get_output(code, filename)
         trace = '\n'.join(trace)
 
         if not cancel:
+            count = loops
             if repeat:
-                count = 2
-            else:
-                count = 1
+                count *= 2
             header = 'Thread 0x[0-9a-f]+:\n'
-            regex = expected_traceback(7, 19, header, count=count)
+            regex = expected_traceback(9, 20, header, count=count)
             self.assertRegex(trace, regex)
         else:
             self.assertEqual(trace, '')
@@ -408,12 +409,17 @@
     @unittest.skipIf(not hasattr(faulthandler, 'dump_tracebacks_later'),
                      'need faulthandler.dump_tracebacks_later()')
     def check_dump_tracebacks_later(self, repeat=False, cancel=False,
-                                  file=False):
+                                    file=False, twice=False):
+        if twice:
+            loops = 2
+        else:
+            loops = 1
         if file:
             with temporary_filename() as filename:
-                self._check_dump_tracebacks_later(repeat, cancel, filename)
+                self._check_dump_tracebacks_later(repeat, cancel,
+                                                  filename, loops)
         else:
-            self._check_dump_tracebacks_later(repeat, cancel, None)
+            self._check_dump_tracebacks_later(repeat, cancel, None, loops)
 
     def test_dump_tracebacks_later(self):
         self.check_dump_tracebacks_later()
@@ -427,6 +433,9 @@
     def test_dump_tracebacks_later_file(self):
         self.check_dump_tracebacks_later(file=True)
 
+    def test_dump_tracebacks_later_twice(self):
+        self.check_dump_tracebacks_later(twice=True)
+
     @unittest.skipIf(not hasattr(faulthandler, "register"),
                      "need faulthandler.register")
     def check_register(self, filename=False, all_threads=False,