Skip to content

Commit f8bdcb2

Browse files
committed
Provide heuristics for the user to provide a library to set tracing to all threads. Fixes microsoft#617
1 parent 02477b5 commit f8bdcb2

File tree

1 file changed

+83
-17
lines changed

1 file changed

+83
-17
lines changed

src/debugpy/_vendored/pydevd/pydevd_tracing.py

+83-17
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from _pydev_imps._pydev_saved_modules import thread, threading
55
from _pydev_bundle import pydev_log, pydev_monkey
66
from os.path import os
7+
import platform
78
try:
89
import ctypes
910
except ImportError:
@@ -130,34 +131,99 @@ def _load_python_helper_lib_uncached():
130131
or hasattr(sys, 'gettotalrefcount') or LOAD_NATIVE_LIB_FLAG in ENV_FALSE_LOWER_VALUES):
131132
return None
132133

134+
libdir = os.path.join(os.path.dirname(__file__), 'pydevd_attach_to_process')
135+
136+
arch = ''
133137
if IS_WINDOWS:
134-
if IS_64BIT_PROCESS:
135-
suffix = 'amd64'
136-
else:
137-
suffix = 'x86'
138+
# prefer not using platform.machine() when possible (it's a bit heavyweight as it may
139+
# spawn a subprocess).
140+
arch = os.environ.get("PROCESSOR_ARCHITEW6432", os.environ.get('PROCESSOR_ARCHITECTURE', ''))
138141

139-
filename = os.path.join(os.path.dirname(__file__), 'pydevd_attach_to_process', 'attach_%s.dll' % (suffix,))
142+
if not arch:
143+
arch = platform.machine()
144+
if not arch:
145+
pydev_log.info('platform.machine() did not return valid value.') # This shouldn't happen...
146+
return None
140147

141-
elif IS_LINUX:
142-
if IS_64BIT_PROCESS:
143-
suffix = 'amd64'
144-
else:
145-
suffix = 'x86'
148+
if IS_WINDOWS:
149+
dllsuffix = '.dll'
150+
suffix_64 = 'amd64'
151+
suffix_32 = 'x86'
146152

147-
filename = os.path.join(os.path.dirname(__file__), 'pydevd_attach_to_process', 'attach_linux_%s.so' % (suffix,))
153+
elif IS_LINUX:
154+
dllsuffix = '.so'
155+
suffix_64 = 'amd64'
156+
suffix_32 = 'x86'
148157

149158
elif IS_MAC:
150-
if IS_64BIT_PROCESS:
151-
suffix = 'x86_64.dylib'
152-
else:
153-
suffix = 'x86.dylib'
154-
155-
filename = os.path.join(os.path.dirname(__file__), 'pydevd_attach_to_process', 'attach_%s' % (suffix,))
159+
dllsuffix = '.dylib'
160+
suffix_64 = 'x86_64'
161+
suffix_32 = 'x86'
156162

157163
else:
158164
pydev_log.info('Unable to set trace to all threads in platform: %s', sys.platform)
159165
return None
160166

167+
if arch.lower() not in ('amd64', 'x86', 'x86_64', 'i386', 'x86'):
168+
# We don't support this processor by default. Still, let's support the case where the
169+
# user manually compiled it himself with some heuristics.
170+
#
171+
# Ideally the user would provide a library in the format: "attach_<arch>.<dllsuffix>"
172+
# based on the way it's currently compiled -- see:
173+
# - windows/compile_windows.bat
174+
# - linux_and_mac/compile_linux.sh
175+
# - linux_and_mac/compile_mac.sh
176+
177+
try:
178+
found = [name for name in os.listdir(libdir) if name.startswith('attach_') and name.endswith(dllsuffix)]
179+
except:
180+
pydev_log.exception('Error listing dir: %s', libdir)
181+
return None
182+
183+
expected_name = 'attach_' + arch + dllsuffix
184+
expected_name_linux = 'attach_linux_' + arch + dllsuffix
185+
186+
filename = None
187+
if expected_name in found: # Heuristic: user compiled with "attach_<arch>.<dllsuffix>"
188+
filename = os.path.join(libdir, expected_name)
189+
190+
elif IS_LINUX and expected_name_linux in found: # Heuristic: user compiled with "attach_linux_<arch>.<dllsuffix>"
191+
filename = os.path.join(libdir, expected_name_linux)
192+
193+
elif len(found) == 1: # Heuristic: user removed all libraries and just left his own lib.
194+
filename = os.path.join(libdir, found[0])
195+
196+
else: # Heuristic: there's one additional library which doesn't seem to be our own. Find the odd one.
197+
filtered = [name for name in found if not name.endswith((suffix_64 + dllsuffix, suffix_32 + dllsuffix))]
198+
if len(filtered) == 1: # If more than one is available we can't be sure...
199+
filename = os.path.join(libdir, found[0])
200+
201+
if filename is None:
202+
pydev_log.info(
203+
'Unable to set trace to all threads in arch: %s (did not find a %s lib in %s).', (
204+
arch, expected_name, libdir
205+
)
206+
)
207+
return None
208+
209+
pydev_log.info('Using %s lib in arch: %s.', filename, arch)
210+
211+
else:
212+
if IS_64BIT_PROCESS:
213+
suffix = suffix_64
214+
else:
215+
suffix = suffix_32
216+
217+
if IS_WINDOWS or IS_MAC: # just the dllsuffix changes
218+
prefix = 'attach_'
219+
elif IS_LINUX: #
220+
prefix = 'attach_linux_' # historically it has a different name
221+
else:
222+
pydev_log.info('Unable to set trace to all threads in platform: %s', sys.platform)
223+
return None
224+
225+
filename = os.path.join(libdir, '%s%s%s' % (prefix, suffix, dllsuffix))
226+
161227
if not os.path.exists(filename):
162228
pydev_log.critical('Expected: %s to exist.', filename)
163229
return None

0 commit comments

Comments
 (0)