|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2020 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a function to patch multiprocessing.Process to support |
|
8 debugging of the process. |
|
9 """ |
|
10 |
|
11 import sys |
|
12 import traceback |
|
13 |
|
14 _debugClient = None |
|
15 _originalProcess = None |
|
16 _originalBootstrap = None |
|
17 |
|
18 |
|
19 def patchMultiprocessing(module, debugClient): |
|
20 """ |
|
21 Function to patch the multiprocessing module. |
|
22 |
|
23 @param module reference to the imported module to be patched |
|
24 @type module |
|
25 @param debugClient reference to the debug client object |
|
26 @type DebugClient |
|
27 """ # __IGNORE_WARNING_D234__ |
|
28 global _debugClient, _originalProcess, _originalBootstrap |
|
29 |
|
30 _debugClient = debugClient |
|
31 |
|
32 _originalProcess = module.process.BaseProcess |
|
33 _originalBootstrap = _originalProcess._bootstrap |
|
34 |
|
35 class ProcessWrapper(_originalProcess): |
|
36 """ |
|
37 Wrapper class for multiprocessing.Process. |
|
38 """ |
|
39 |
|
40 def _bootstrap(self, *args, **kwargs): |
|
41 """ |
|
42 Wrapper around _bootstrap to start debugger. |
|
43 |
|
44 @param args function arguments |
|
45 @type list |
|
46 @param kwargs keyword only arguments |
|
47 @type dict |
|
48 @return exit code of the process |
|
49 @rtype int |
|
50 """ |
|
51 _debugging = False |
|
52 if _debugClient.debugging and _debugClient.multiprocessSupport: |
|
53 scriptName = sys.argv[0] |
|
54 if not _debugClient.skipMultiProcessDebugging(scriptName): |
|
55 _debugging = True |
|
56 try: |
|
57 ( |
|
58 wd, |
|
59 host, |
|
60 port, |
|
61 exceptions, |
|
62 tracePython, |
|
63 redirect, |
|
64 noencoding, |
|
65 ) = _debugClient.startOptions[:7] |
|
66 _debugClient.startDebugger( |
|
67 sys.argv[0], |
|
68 host=host, |
|
69 port=port, |
|
70 exceptions=exceptions, |
|
71 tracePython=tracePython, |
|
72 redirect=redirect, |
|
73 passive=False, |
|
74 multiprocessSupport=True, |
|
75 ) |
|
76 except Exception: |
|
77 print( |
|
78 # __IGNORE_WARNING_M801__ |
|
79 "Exception during multiprocessing bootstrap init:" |
|
80 ) |
|
81 traceback.print_exc(file=sys.stdout) |
|
82 sys.stdout.flush() |
|
83 raise |
|
84 |
|
85 exitcode = _originalBootstrap(self, *args, **kwargs) |
|
86 |
|
87 if _debugging: |
|
88 _debugClient.progTerminated(exitcode, "process finished") |
|
89 |
|
90 return exitcode |
|
91 |
|
92 _originalProcess._bootstrap = ProcessWrapper._bootstrap |