bpo-29102: Add a unique ID to PyInterpreterState. (#1639) · python/cpython@e377416 (original) (raw)
1
1
`# Run the _testcapi module tests (tests for the Python/C API): by defn,
`
2
2
`# these are all functions testcapi exports whose name begins with 'test'.
`
3
3
``
``
4
`+
from collections import namedtuple
`
4
5
`import os
`
5
6
`import pickle
`
``
7
`+
import platform
`
6
8
`import random
`
7
9
`import re
`
8
10
`import subprocess
`
`@@ -384,12 +386,91 @@ def run_embedded_interpreter(self, *args):
`
384
386
`return out, err
`
385
387
``
386
388
`def test_subinterps(self):
`
387
``
`-
This is just a "don't crash" test
`
388
389
`out, err = self.run_embedded_interpreter("repeated_init_and_subinterpreters")
`
389
``
`-
if support.verbose:
`
390
``
`-
print()
`
391
``
`-
print(out)
`
392
``
`-
print(err)
`
``
390
`+
self.assertEqual(err, "")
`
``
391
+
``
392
`+
The output from _testembed looks like this:
`
``
393
`+
--- Pass 0 ---
`
``
394
`+
interp 0 <0x1cf9330>, thread state <0x1cf9700>: id(modules) = 139650431942728
`
``
395
`+
interp 1 <0x1d4f690>, thread state <0x1d35350>: id(modules) = 139650431165784
`
``
396
`+
interp 2 <0x1d5a690>, thread state <0x1d99ed0>: id(modules) = 139650413140368
`
``
397
`+
interp 3 <0x1d4f690>, thread state <0x1dc3340>: id(modules) = 139650412862200
`
``
398
`+
interp 0 <0x1cf9330>, thread state <0x1cf9700>: id(modules) = 139650431942728
`
``
399
`+
--- Pass 1 ---
`
``
400
`+
...
`
``
401
+
``
402
`+
interp_pat = (r"^interp (\d+) <(0x[\dA-F]+)>, "
`
``
403
`+
r"thread state <(0x[\dA-F]+)>: "
`
``
404
`+
r"id(modules) = ([\d]+)$")
`
``
405
`+
Interp = namedtuple("Interp", "id interp tstate modules")
`
``
406
+
``
407
`+
main = None
`
``
408
`+
lastmain = None
`
``
409
`+
numinner = None
`
``
410
`+
numloops = 0
`
``
411
`+
for line in out.splitlines():
`
``
412
`+
if line == "--- Pass {} ---".format(numloops):
`
``
413
`+
if numinner is not None:
`
``
414
`+
self.assertEqual(numinner, 5)
`
``
415
`+
if support.verbose:
`
``
416
`+
print(line)
`
``
417
`+
lastmain = main
`
``
418
`+
main = None
`
``
419
`+
mainid = 0
`
``
420
`+
numloops += 1
`
``
421
`+
numinner = 0
`
``
422
`+
continue
`
``
423
`+
numinner += 1
`
``
424
+
``
425
`+
self.assertLessEqual(numinner, 5)
`
``
426
`+
match = re.match(interp_pat, line)
`
``
427
`+
if match is None:
`
``
428
`+
self.assertRegex(line, interp_pat)
`
``
429
+
``
430
`+
The last line in the loop should be the same as the first.
`
``
431
`+
if numinner == 5:
`
``
432
`+
self.assertEqual(match.groups(), main)
`
``
433
`+
continue
`
``
434
+
``
435
`+
Parse the line from the loop. The first line is the main
`
``
436
`+
interpreter and the 3 afterward are subinterpreters.
`
``
437
`+
interp = Interp(*match.groups())
`
``
438
`+
if support.verbose:
`
``
439
`+
print(interp)
`
``
440
`+
if numinner == 1:
`
``
441
`+
main = interp
`
``
442
`+
id = str(mainid)
`
``
443
`+
else:
`
``
444
`+
subid = mainid + numinner - 1
`
``
445
`+
id = str(subid)
`
``
446
+
``
447
`+
Validate the loop line for each interpreter.
`
``
448
`+
self.assertEqual(interp.id, id)
`
``
449
`+
self.assertTrue(interp.interp)
`
``
450
`+
self.assertTrue(interp.tstate)
`
``
451
`+
self.assertTrue(interp.modules)
`
``
452
`+
if platform.system() == 'Windows':
`
``
453
`+
XXX Fix on Windows: something is going on with the
`
``
454
`+
pointers in Programs/_testembed.c. interp.interp
`
``
455
`+
is 0x0 and # interp.modules is the same between
`
``
456
`+
interpreters.
`
``
457
`+
continue
`
``
458
`+
if interp is main:
`
``
459
`+
if lastmain is not None:
`
``
460
`+
A new main interpreter may have the same interp
`
``
461
`+
and/or tstate pointer as an earlier finalized/
`
``
462
`+
destroyed one. So we do not check interp or
`
``
463
`+
tstate here.
`
``
464
`+
self.assertNotEqual(interp.modules, lastmain.modules)
`
``
465
`+
else:
`
``
466
`+
A new subinterpreter may have the same
`
``
467
`+
PyInterpreterState pointer as a previous one if
`
``
468
`+
the earlier one has already been destroyed. So
`
``
469
`+
we compare with the main interpreter. The same
`
``
470
`+
applies to tstate.
`
``
471
`+
self.assertNotEqual(interp.interp, main.interp)
`
``
472
`+
self.assertNotEqual(interp.tstate, main.tstate)
`
``
473
`+
self.assertNotEqual(interp.modules, main.modules)
`
393
474
``
394
475
`@staticmethod
`
395
476
`def _get_default_pipe_encoding():
`