Attaching Python debugger - python

I'd like to attach a Python debugger to a running process. Following this comment, I tried pdb-clone but have gotten confused. Here's the script I'm attaching to:
import os
import time
from pdb_clone import pdbhandler
pdbhandler.register()
def loop(my_pid):
print("Entering loop")
while True:
x = 'frog'
time.sleep(0.5)
print("Out of Loop")
if __name__ == '__main__':
my_pid = os.getpid()
print("pid = ", my_pid)
loop(my_pid)
If I run python3 target_code_1.py in one terminal and see PID = 95439, then in a second terminal try
sudo pdb-attach --kill --pid 95439
I get an error message (which I include below).
However, suppose I simultaneously run python3 target_code_1.py in a third terminal. I can now run sudo pdb-attach --kill --pid 95439 without error, but when I print my_pid, the value is 95440. On the other hand, if I run sudo pdb-attach --kill --pid 95440 and print my_pid, the value is 95439. (In other words, it looks like pdb-attach has swapped which thread it is attaching to.) This behavior appears to be repeatable. What is going on?
For the record, the initial error message is as follows:
sudo pdb-attach --kill --pid 95440
Traceback (most recent call last):
File "/usr/local/bin/pdb-attach", line 4, in <module>
attach.main()
File "/usr/local/lib/python3.7/site-packages/pdb_clone/attach.py", line 646, in main
attach(address)
File "/usr/local/lib/python3.7/site-packages/pdb_clone/attach.py", line 596, in attach
for count in asock.connect_retry(address, verbose):
File "/usr/local/lib/python3.7/site-packages/pdb_clone/attach.py", line 115, in connect_retry
self.connect(address)
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncore.py", line 342, in connect
raise OSError(err, errorcode[err])
OSError: [Errno 22] EINVAL
FWIW, I'm running on macOS Mojave 10.14.2, Python 3.7.0, Clang 9.1.0.
(If I am solving this problem the wrong way, e.g., if there is a better Python module to use that can attach to live process, I'd be happy to use it instead.)

Related

P4Python run method does not work on empty folder

I want to search a Perforce depot for files.
I do this from a python script and use the p4python library command:
list = p4.run("files", "//mypath/myfolder/*")
This works fine as long as myfolder contains some files. I get a python list as a return value. But when there is no file in myfolder the program stops running and no error message is displayed. My goal is to get an empty python list, so that I can see that this folder doesn't contain any files.
Does anybody has some ideas? I could not find information in the p4 files documentation and on StackOverflow.
I'm going to guess you've got an exception handler around that command execution that's eating the exception and exiting. I wrote a very simple test script and got this:
C:\Perforce\test>C:\users\samwise\AppData\local\programs\python\Python36-32\python files.py
Traceback (most recent call last):
File "files.py", line 6, in <module>
print(p4.run("files", "//depot/no such path/*"))
File "C:\users\samwise\AppData\local\programs\python\Python36-32\lib\site-packages\P4.py", line 611, in run
raise e
File "C:\users\samwise\AppData\local\programs\python\Python36-32\lib\site-packages\P4.py", line 605, in run
result = P4API.P4Adapter.run(self, *flatArgs)
P4.P4Exception: [P4#run] Errors during command execution( "p4 files //depot/no such path/*" )
[Error]: "//depot/no such path/* - must refer to client 'Samwise-dvcs-1509687817'."
Try something like this ?
import os
if len(os.listdir('//mypath/myfolder/') ) == 0: # Do not execute p4.run if directory is empty
list = []
else:
list = p4.run("files", "//mypath/myfolder/*")

Issue with Popen running as another user (macOS)

I have a python script that is being run on some Macs by my MDM tool. This means that the script is being run as root. There is a part of the script I need to run as the currently logged in local user on the account. I found this article below for using Popen to do this:
Run child processes as a different user from a long-running process
However, I am getting an error when I attempt to use this method on any pre macOS 10.13 computers. These are still modern OS versions such as 10.12 and 10.11. I have not been able to track this error down. Please see the code below.
Note: There are likely some extra import statements as this is pulled from a larger script. This snippet should work as-is.
#!/usr/bin/python
import subprocess
import platform
import os
import pwd
import sys
import hashlib
import plistlib
import time
from SystemConfiguration import SCDynamicStoreCopyConsoleUser
from distutils.version import StrictVersion as SV
def getLoggedInUserUID():
userUID = SCDynamicStoreCopyConsoleUser(None, None, None)[1]
return userUID
def getLoggedInUsername():
username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]
return username
def getLoggedInUserGID():
username = getLoggedInUsername()
pwRecord = pwd.getpwnam(username)
userGID = pwRecord.pw_gid
return userGID
def getLoggedInUserHomeDir():
username = getLoggedInUsername()
pwRecord = pwd.getpwnam(username)
homeDir = pwRecord.pw_dir
return homeDir
def demote():
def result():
os.setgid(getLoggedInUserGID())
os.setuid(getLoggedInUserUID())
return result
def setupEnvironment():
environment = os.environ.copy()
environment['HOME'] = str(getLoggedInUserHomeDir())
environment['LOGNAME'] = str(getLoggedInUsername())
environment['PWD'] = str(getLoggedInUserHomeDir())
environment['USER'] = str(getLoggedInUsername())
return environment
def launchCommand():
command = ['echo', 'whoami']
process = subprocess.Popen(command,
stdout=subprocess.PIPE,
preexec_fn=demote(),
cwd=str(getLoggedInUserHomeDir()),
env=setupEnvironment())
def main():
launchCommand()
if __name__== "__main__":
main()
The error that I get is:
Traceback (most recent call last):
File "testScript.py", line 60, in <module>
main()
File "testScript.py", line 57, in main
launchCommand()
File "testScript.py", line 54, in launchCommand
env=setupEnvironment())
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 710, in __init__
errread, errwrite)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1335, in _execute_child
raise child_exception
KeyError: 'getpwnam(): name not found: '
It looks like it is missing some key value but I cannot for the like of me figure out what it is. Any help in tracking this down so I can run the command as the logged in user would help greatly.
Thanks in Advance,
Ed
The way that I did in my small mdm managed environment is like this:
I developed small windowless LoginItem helperApp that starts for every open user session on the mac and listens for custom distributed system notification. It also has a function for executing terminal commands without showing terminal window (You can find examples for this on stackowerflow).
I transmit to all apps currently running on the system two params in the notification: an username and a terminal command string. All of the users running instances get the notification, than they check the username for if they run in that user and the one that does - executes the command in that users name.
Try this if it fits your requirement.

winpdb not working with python 3.3

I can't get rpdb2 to run with python 3.3, while that should be possible according to several sources.
$ rpdb2 -d myscript.py
A password should be set to secure debugger client-server communication.
Please type a password:x
Password has been set.
Traceback (most recent call last):
File "/usr/local/bin/rpdb2", line 31, in <module>
rpdb2.main()
File "/usr/local/lib/python3.3/dist-packages/rpdb2.py", line 14470, in main
StartServer(_rpdb2_args, fchdir, _rpdb2_pwd, fAllowUnencrypted, fAllowRemote, secret)
File "/usr/local/lib/python3.3/dist-packages/rpdb2.py", line 14212, in StartServer
g_module_main = -1
File "/usr/local/lib/python3.3/dist-packages/rpdb2.py", line 14212, in StartServer
g_module_main = -1
File "/usr/local/lib/python3.3/dist-packages/rpdb2.py", line 7324, in trace_dispatch_init
self.__set_signal_handler()
File "/usr/local/lib/python3.3/dist-packages/rpdb2.py", line 7286, in __set_signal_handler
handler = signal.getsignal(value)
File "/usr/local/lib/python3.3/dist-packages/rpdb2.py", line 13682, in __getsignal
handler = g_signal_handlers.get(signum, g_signal_getsignal(signum))
ValueError: signal number out of range
The version of rpdb2 is RPDB 2.4.8 - Tychod.
I installed it by running pip-3.3 install winpdb.
Any clues?
Got the same problem today here is what i've done for it to work.
Still i'm not too sure if this is correct to do it this way.
From:
def __getsignal(signum):
handler = g_signal_handlers.get(signum, g_signal_getsignal(signum))
return handler
To:
def __getsignal(signum):
try:
# The problems come from the signum which was 0.
g_signal_getsignal(signum)
except ValueError:
return None
handler = g_signal_handlers.get(signum, g_signal_getsignal(signum))
return handler
This function shall be at line 13681 or something like.
The reason of a problem is the extended list of attributes in a signal module that was used by rpdb2 to list all signals. New python versions added attributes like SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK
So the filtering should be extended too (patch changes just one line):
--- rpdb2.py
+++ rpdb2.py
## -7278,11 +7278,11 ##
def __set_signal_handler(self):
"""
Set rpdb2 to wrap all signal handlers.
"""
for key, value in list(vars(signal).items()):
- if not key.startswith('SIG') or key in ['SIGRTMIN', 'SIGRTMAX'] or key.startswith('SIG_'):
+ if not key.startswith('SIG') or key in ['SIG_IGN', 'SIG_DFL', 'SIGRTMIN', 'SIGRTMAX']:
continue
handler = signal.getsignal(value)
if handler in [signal.SIG_IGN, signal.SIG_DFL]:
continue
Unfortunately there is no current official development or fork of winpdb, so by now this patch would be just stored on SO.

Something wrong with ViewClient.connectToDeviceOrExit()

I'm recently started to use python with mobile app automation, as i decided to use python, the main instruments that I've found were monkeyrunner and androidviewclient.
But there is the first issue with which i dont know what to do:
package = 'com.mypackage.android'
activity = '.launchActivity'
component = package + "/" + activity
device, serialno = ViewClient.connectToDeviceOrExit()
device.startActivity(component=component)
time.sleep(3)
vc = ViewClient(device, serialno)
vc.dump()
showMenu = vc.findViewById("id/no_id/8")
showMenu.touch()
as i'm running it in windows cmd - monkeyrunner mypath\test-case1.py
i receive an exception:
131213 18:42:32.555:S [MainThread] [com.android.monkeyrunner.MonkeyRunnerOptions] Script terminated due to an exception
131213 18:42:32.555:S [MainThread] [com.android.monkeyrunner.MonkeyRunnerOptions]Traceback (most recent call last):
File "C:\Python27\tests\1.py", line 26, in <module>
device, serialno = ViewClient.connectToDeviceOrExit()
File "C:\Program Files (x86)\Android\AndroidViewClient\AndroidViewClient-maste
r\AndroidViewClient\src\com\dtmilano\android\viewclient.py", line 1381, in conne
ctToDeviceOrExit
ViewClient.setAlarm(timeout+5)
File "C:\Program Files (x86)\Android\AndroidViewClient\AndroidViewClient-maste
r\AndroidViewClient\src\com\dtmilano\android\viewclient.py", line 1341, in setAl
arm
signal.alarm(timeout)
File "C:\Program Files (x86)\Android\android-sdk\tools\lib\jython-standalone-2
.5.3.jar\Lib\signal.py", line 222, in alarm
NotImplementedError: alarm not implemented on this platform
am I doing something wrong? Please help.
Thank you a lot!
This is how setAlarm looks like
#staticmethod
def setAlarm(timeout):
osName = platform.system()
if osName.startswith('Windows'): # alarm is not implemented in Windows
return
signal.alarm(timeout)
so, it tries to identify that is Windows and then not invoking signal.alarm() which is not implemented, but for some reason it fails in your case.
Try to print the result of osName to see what went wrong.
UPDATE
Now I see, you are using monkeyrunner as the interpreter but AndroidViewClient >= 4.0.0 is 100% pure python, so you should run your scripts using a python 2.x interpreter.

What permissions are required for subprocess.Popen?

The following code:
gb = self.request.form['groupby']
typ = self.request.form['type']
tbl = self.request.form['table']
primary = self.request.form.get('primary', None)
if primary is not None:
create = False
else:
create = True
mdb = tempfile.NamedTemporaryFile()
mdb.write(self.request.form['mdb'].read())
mdb.seek(0)
csv = tempfile.TemporaryFile()
conversion = subprocess.Popen(("/Users/jondoe/development/mdb-export", mdb.name, tbl,),stdout=csv)
Causes the this error when calling the last line i.e. 'conversion =' in OS X.
Traceback (innermost last):
Module ZPublisher.Publish, line 119, in publish
Module ZPublisher.mapply, line 88, in mapply
Module ZPublisher.Publish, line 42, in call_object
Module circulartriangle.mdbtoat.mdb, line 62, in __call__
Module subprocess, line 543, in __init__
Module subprocess, line 975, in _execute_child
OSError: [Errno 13] Permission denied
I've tried chmod 777 /Users/jondoe/development/mdb-export - what else might be required?
Assuming that permissions on parent folders are correct (i.e. all parent folders should have +x permission), try adding:
shell=True
to the Popen command such as:
subprocess.Popen(("/Users/jondoe/development/mdb-export", mdb.name, tbl,), stdout=csv, shell=True)
It seems the 'Permissions denied error' was orginally coming from Popen trying to execute mdb-export from the wrong location (and to compound things, with the wrong permissions).
If mdbtools is installed, the following works fine and inherits the correct permissions without the need for sudo etc.
subprocess.Popen(("mdb-export", mdb.name, tbl,),stdout=csv)
(Worth noting, I got myself into a muddle for a while, having forgotten that Popen is for opening executables, not folders or non-exectable files in folders)
Thanks for all your responses, they all made for interesting reading regardless :)
Can you feed "sudo" to subprocess? See this SO thread.
#Jon Hadley, from the interpreter:
>>> import subprocess
>>> p = subprocess.call(['sudo','/usr/bin/env'])
PASSWORD:
[snip]
USER=root
USERNAME=root
SUDO_COMMAND=/usr/bin/env
SUDO_USER=telliott99
SUDO_UID=501
SUDO_GID=20
From Terminal on OS X, I have to do sudo when I run the script:
$ sudo python test.py
then this (in test.py) gives the same output as before:
import subprocess
p = subprocess.Popen('/usr/bin/env')
Getting subprocess to directly handle the authentication from a script is probably not a good idea, since it hides the privilege escalation. But you could look at pexpect and this SO answer.
You also need to ensure read and execute permissions for the user running that code on the directories up the chain - /Users, /Users/jondoe and /Users/jondoe/development.

Categories

Resources