[3.6] bpo-31234: Add test.support.wait_threads_exit() (GH-3578) (GH-7… · python/cpython@5dbb48a

@@ -59,12 +59,13 @@ def task(self, ident):

5959

self.done_mutex.release()

60606161

def test_starting_threads(self):

62-

# Basic test for thread creation.

63-

for i in range(NUMTASKS):

64-

self.newtask()

65-

verbose_print("waiting for tasks to complete...")

66-

self.done_mutex.acquire()

67-

verbose_print("all tasks done")

62+

with support.wait_threads_exit():

63+

# Basic test for thread creation.

64+

for i in range(NUMTASKS):

65+

self.newtask()

66+

verbose_print("waiting for tasks to complete...")

67+

self.done_mutex.acquire()

68+

verbose_print("all tasks done")

68696970

def test_stack_size(self):

7071

# Various stack size tests.

@@ -94,12 +95,13 @@ def test_nt_and_posix_stack_size(self):

9495

verbose_print("trying stack_size = (%d)" % tss)

9596

self.next_ident = 0

9697

self.created = 0

97-

for i in range(NUMTASKS):

98-

self.newtask()

98+

with support.wait_threads_exit():

99+

for i in range(NUMTASKS):

100+

self.newtask()

99101100-

verbose_print("waiting for all tasks to complete")

101-

self.done_mutex.acquire()

102-

verbose_print("all tasks done")

102+

verbose_print("waiting for all tasks to complete")

103+

self.done_mutex.acquire()

104+

verbose_print("all tasks done")

103105104106

thread.stack_size(0)

105107

@@ -109,25 +111,28 @@ def test__count(self):

109111

mut = thread.allocate_lock()

110112

mut.acquire()

111113

started = []

114+112115

def task():

113116

started.append(None)

114117

mut.acquire()

115118

mut.release()

116-

thread.start_new_thread(task, ())

117-

while not started:

118-

time.sleep(POLL_SLEEP)

119-

self.assertEqual(thread._count(), orig + 1)

120-

# Allow the task to finish.

121-

mut.release()

122-

# The only reliable way to be sure that the thread ended from the

123-

# interpreter's point of view is to wait for the function object to be

124-

# destroyed.

125-

done = []

126-

wr = weakref.ref(task, lambda _: done.append(None))

127-

del task

128-

while not done:

129-

time.sleep(POLL_SLEEP)

130-

self.assertEqual(thread._count(), orig)

119+120+

with support.wait_threads_exit():

121+

thread.start_new_thread(task, ())

122+

while not started:

123+

time.sleep(POLL_SLEEP)

124+

self.assertEqual(thread._count(), orig + 1)

125+

# Allow the task to finish.

126+

mut.release()

127+

# The only reliable way to be sure that the thread ended from the

128+

# interpreter's point of view is to wait for the function object to be

129+

# destroyed.

130+

done = []

131+

wr = weakref.ref(task, lambda _: done.append(None))

132+

del task

133+

while not done:

134+

time.sleep(POLL_SLEEP)

135+

self.assertEqual(thread._count(), orig)

131136132137

def test_save_exception_state_on_error(self):

133138

# See issue #14474

@@ -140,16 +145,14 @@ def mywrite(self, *args):

140145

except ValueError:

141146

pass

142147

real_write(self, *args)

143-

c = thread._count()

144148

started = thread.allocate_lock()

145149

with support.captured_output("stderr") as stderr:

146150

real_write = stderr.write

147151

stderr.write = mywrite

148152

started.acquire()

149-

thread.start_new_thread(task, ())

150-

started.acquire()

151-

while thread._count() > c:

152-

time.sleep(POLL_SLEEP)

153+

with support.wait_threads_exit():

154+

thread.start_new_thread(task, ())

155+

started.acquire()

153156

self.assertIn("Traceback", stderr.getvalue())

154157155158

@@ -181,13 +184,14 @@ def enter(self):

181184

class BarrierTest(BasicThreadTest):

182185183186

def test_barrier(self):

184-

self.bar = Barrier(NUMTASKS)

185-

self.running = NUMTASKS

186-

for i in range(NUMTASKS):

187-

thread.start_new_thread(self.task2, (i,))

188-

verbose_print("waiting for tasks to end")

189-

self.done_mutex.acquire()

190-

verbose_print("tasks done")

187+

with support.wait_threads_exit():

188+

self.bar = Barrier(NUMTASKS)

189+

self.running = NUMTASKS

190+

for i in range(NUMTASKS):

191+

thread.start_new_thread(self.task2, (i,))

192+

verbose_print("waiting for tasks to end")

193+

self.done_mutex.acquire()

194+

verbose_print("tasks done")

191195192196

def task2(self, ident):

193197

for i in range(NUMTRIPS):

@@ -225,11 +229,10 @@ def setUp(self):

225229

@unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')

226230

@support.reap_threads

227231

def test_forkinthread(self):

228-

running = True

229232

status = "not set"

230233231234

def thread1():

232-

nonlocal running, status

235+

nonlocal status

233236234237

# fork in a thread

235238

pid = os.fork()

@@ -244,13 +247,11 @@ def thread1():

244247

# parent

245248

os.close(self.write_fd)

246249

pid, status = os.waitpid(pid, 0)

247-

running = False

248250249-

thread.start_new_thread(thread1, ())

250-

self.assertEqual(os.read(self.read_fd, 2), b"OK",

251-

"Unable to fork() in thread")

252-

while running:

253-

time.sleep(POLL_SLEEP)

251+

with support.wait_threads_exit():

252+

thread.start_new_thread(thread1, ())

253+

self.assertEqual(os.read(self.read_fd, 2), b"OK",

254+

"Unable to fork() in thread")

254255

self.assertEqual(status, 0)

255256256257

def tearDown(self):