Debugging non-responsive python/PyQt application in PyCharm - python-3.x

How do you go about debugging a non-responsive python/PyQt application in PyCharm?
I am an experienced programmer, but new to all thing python. I have been given a large application (36,000 lines), which works under Windows, to port to Linux.
Having made just a handful of changes for OS-specific stuff, when I run the application it comes up with its main window. But then after a few seconds it becomes dimmed, and when I close the window I am asked to confirm to end "the window is not responding".
(Aside: On a whim I decided to try running the app via sudo, and surprisingly it works fine. I have tried doing strace running as root versus non-root, but I'm fairly sure there is nothing obvious in the way of file accesses/permissions etc. that differs. This may be a clue, but just as likely to be a red-herring, e.g. if it's an "uninitialized variable".)
If I debug it inside PyCharm, at that point I expect to click the "Pause Program" button, so that I can get a trace back and begin to see where it is in the code, and start stepping or whatever. However, that button does nothing at this stage? Maybe it only "works" when on "a python instruction"?
If I force a core dump (from the keyboard) and examine with gdb, I can see that the stack frame shows it is way down inside libQtCore/libQtGui, in processEvents on a call to read.
So how do I begin to go about debugging why it is (presumably) busy doing something at this point, or at least not responding? Any tips would be welcome. I do hope this question will not fall foul of SO's "too general" policy, any tips to get someone going on debugging a "non-responsive" program would be welcome.

To answer my own question, since no responses seem to be forthcoming.
In this case, the problem turned out to lie in a file which is imported into other files, named pyperclip.py. That had code outside of any function, and in a path through the source executed under Linux but I think not under Windows, which included:
app = PyQt4.QtGui.QApplication([])
cb = PyQt4.QtGui.QApplication.clipboard()
Clearly some attempt to gain a clipboard object. For whatever reason, this appears to work when run as su, but when run as the logged on user it causes the whole application to "hang". Removing those two lines solved the unresponsiveness.
In terms of what I learnt from this for debugging unresponsive applications: you need to debug not from the entry point of the program, as I would have expected, but rather right from the start of each file, and actually step into each import line just in case it is executing some initial code. Horrible!

Related

Linux - Open terminal for input/output

I'm coding a Rust app and since it's fairly small and there don't appear to be any stable UI frameworks, I've made it run in the console using println! and whatnot for input/output. However since this program is intended to be used by people directly after downloading from the internet (due to its use case), they're likely to just double click on it instead of navigating to their downloads directory in a terminal and running it from there.
This is a problem because on Linux, it runs in the background waiting for input and looks like it's not working. On Windows, Rust programs do open in CMD by default. (and in fact many of the search results for my question were about disabling this behavior - the exact opposite of what I want!).
So is it possible to somehow make my application open in the system's default terminal? My preferred way would be to somehow embed in the executable to open in terminal (similar to the -mconsole compiler flag on MinGW). Otherwise would it be possible to detect it's in the background and fork it into a terminal? If that's not possible then is it at least possible to detect that the app is not running in a terminal and throw up a message box telling the user to run in a terminal?
My app is cross-platform but I'm OK with writing code conditionally compiled on one OS.
One typical way would be to distribute a program.sh along with your executable. If .sh extension is bound to opening a terminal in their window manager of choice, it would open automatically. If not - it is enough of a hint for running it from the shell.
Without this file you could:
Detect if the program is already running inside a terminal can be done with isatty(). There's a crate for it.
If not, spawn the terminal app process (see process::Command) and relaunch the program with it by passing its path to the terminal command line options. As #Caesar mentioned there's a bunch of popular terminals that you might want to check for presence on Linux. If nothing is found, xterm could sometimes be a fallback.

Pure Data freezes when trying to record

Working with Pure Data, trying to record audio output from a patch I've made, and am 1) unable to create a file within pure data to write to and 2) attempting to use the writesf~ object causes the program to freeze after about two to three seconds. I suspect the two things are related- perhaps the program is attempting to write data somewhere, somehow, but it's going in the wrong place or some such and causing the program to freeze?
I've uninstalled the latest Pure Data release (0.51-1) and installed an earlier stable release (0.5-2) and even tried an alternative called "purr data (latest release)" all with the exact same result on my windows 10 acer laptop: no file created, and program freezes after a few seconds.
I'm testing with this patch:
I first click on the message that reads "open rec.wav" then the start then the stop, and if I take longer than three or so seconds to click on "stop" the program freezes, otherwise nothing at all happens.
I have performed system wide search for the audio file, including the folder that the patch is in, all to no avail.
Any trouble shooting hints will be carefully attempted.
Are you sure you have write-permissions on the target directory?
If your example you use rec.wav which has no explicit target directory (and is just using the "current", so it's hard to tell from outside what this directory would be).
#max-n's answer suggests to use /tmp/foo.wav which is an illegal directory on Windows. Due to a known bug, using an illegal (or otherwise non-writable) path will lock up Pd.
If your "current" directory happens to be your system root (aka C:\), you might well lack the permissions to write there.
You could check by starting the Pd from the cmdline and see whether the terminal spits out any weird errors:
⊞ Win+R
type cmd and hit Enter
in the opening terminal type the full path to your Pd-executable, e.g.:
C:\Program Files\Pd\bin\pd + Enter
(ideally leave out the extension (that is: use .../pd rather than .../pd.exe)
If the problem is indeed a permission problem, you can simply work around it by specifying the full path of the output file (and make sure that it is in a writable directory).
The easiest way to do this is by using a file-selector to choose the output file:
[bang(
|
[savepanel]
|
[open $1(
|
[writesf~]
There might be a reason why the helpfile uses a [delay 1000] to schedule a stop message in a predefined time.

What happens when I use stop command without any args?

I just accidentally typed stop instead of exit in a bash script. When I execute it my Xubuntu went to the login screen and when I logged in, everything was closed and it was like I just started the computer.
I then went to my Ubuntu on a virtual box and executed stop in the terminal. Then some windows was closed and some frames around other windows disappeared.
I'm a Linux noob but when I looked at the stop command info it looks like you need to have an argument to use the stop command.
Is this just a bug or is this supposed to happen? If it's supposed, then I'm really curious of whats happening. My guessing is that it will try to kill all ongoing processes.
I'm new here so I hope this it not a stupid question and its really hard to google on a common word like stop :/
man stop should tell you what it does. E.G. http://manpages.ubuntu.com/manpages/precise/en/man8/stop.8.html
I think it should tell you it needs an argument for a name of a job to stop.
However it appears from what you describe that it's stopping the X11 window manager?

Autostart GUI application with LXDE session

There's quite a bit of information out there on this topic, but for some reason I just can't get it to work. This is on a raspberry pi running the 'DietPi' flavor over the raspian distro, and is perhaps what separates my question from the others.
So I have a GUI application that I wish to launch at boot, after the LXDE session has begun. So I have utilized the following file here:
/etc/xdg/lxsession/LXDE/autostart
and added the line:
#/myapplication
This works, however, it launches multiple instances of this program, and the first one always crashes. This creates problems because there's some competition for resources (IO, files, etc). So what I did was create script file, /myapplication-autostart.sh instead like so:
if pgrep "myapplication" > /dev/null
then
echo "my application is already running"
else
/myapplication
fi
and then changed /etc/xdg/lxsession/LXDE/autostart to #/myapplication-autostart.sh. Now what I find is the program launches once, but the instance crashes. It crashes when it attempts to create a window (opencv imshow). This is strange because the program will also run headless if an X-session is not available, but for some reason it crashes and I do not know where to check why.
Also, to test it wasn't an issue with the script file, I commented everything out except the /myapplication and I have found the script file runs in a continuous loop and every time I close the application it opens back up. I'm not sure why this is either.
I've tried adding a sleep delay in the script and it does not help. For whatever reason, it seems the LXDE autostart script is ran at least 3 times when booting the pi and the circumstances around the first cause the program to crash. Does anybody understand this sequence and behavior of calling this autostart script?
It is also possible to use the XDG standard Autostart - which is independent of the used desktop environment - by placing desktop files at
$XDG_CONFIG_HOME/autostart (by default ~/.config/autostart)
or for system-wide autostarts at $XDG_CONFIG_DIRS/autostart (by default /etc/xdg/autostart).
Such a .desktop-file could look like:
[Desktop Entry]
Type=Application
Version=1.0
Name=JDownloader
Exec=/usr/local/bin/my-application.sh
Categories=Utilities
The specification of desktop-files can be found at freedesktop.org.
Here was the final solution...
/etc/xdg/lxsession/LXDE/autostart added the line:
/myapplication-autostart.sh
and /myapplication-autostart.sh was changed to:
#!/bin/bash
if pgrep "myapplication" > /dev/null
then
echo "my application is already running"
else
if [[ "$DISPLAY" = ":0" ]]
then
/myapplication
fi
fi
I had to write the display variable to file in combination with the errors to file to discover the issue. At login 2 X sessions were created, display ":1" and display ":0", in that sequence. Display ":1" crashed because, although not headless, it was not initialized to a particular resolution and there was some resizing code in my program. Display ":0" was the actual display on the HDMI out and the one I wanted. Really, the conditional check to see if the application isn't necessary but I left it in there to be safe. I could have also left the # on the LXDE autostart file but it got annoying in the cases I wanted to close the application because it'd keep re-opening. Possibly I'll put it back later.
Thanks for the help!
First, some comments about opening several instances of the program: when you use "#" at the beginning of the line on the startup file (ex.: #/myapplication), this requests your system to try to launch the program, but if the program fails to open correctly, then the system will try to open it multiple times until it opens correctly -- if you remove "#" from the line beginning, then the system will only try to open the program once.
Now, to find out why the program is failing, I advise you to add
2> /file/log
to the end of every command on your script. Doing so would append any error message to a log (/file/log), and analyzing those error messages would be key to find out why the program is misbehaving.
One important note: if your program needs root privileges to run, then it will fail when called via /etc/xdg/lxsession/LXDE/autostart, as this method calls programs without elevated permissions.
This is an old thread but I was having problems getting autostart to start all the tasks listed. After many days I concluded there were one or more "invisible" characters that autostart didn't like. So I deleted the lines for the tasks that didn't start and retyped them. That solved the problem!
I think I corrupted the lines because I was editing some of the lines on my Windows computer. It was likely inserting CR with LF or some other stuff. I WILL NEVER EDIT TEXT FOR LINUX USING WINDOWS!
Maybe someone else will hit this problem and this may help them. I don't know where else to put this information.

In gnome w/ xmonad, how can I call a script when a monitor is plugged in OR when docking my laptop?

Problem:
I have an extra set of top and bottom gnome-panels for a second monitor. When I undock my lenovo Thinkpad (T510), the extra top and bottom panels remain, so I have two on top and two on the bottom. I am currently running a RHEL6/Fedora (x86_64) gnome (2.28.2) instance with xmonad (0.9.1-6.1.el6) set as the window manager, using the xmonad extensions to work within gnome.
Tried:
I've used acpi and found a code for docking and undocking, but when I try to utilize a script I found in this blog post, it gets zero for the call to xrandr. The script works when called on its own from the terminal. I've tried calling a separate looping script in its own thread and it keeps getting zero for the value, long after the screen(s) update(s).
I have figured out how to have a script loop every X seconds and check for a file which is touched into existence in the event of the script getting a zero, then performing the necessary change, but I don't like that approach.
Question:
I'm hoping someone knows a place I can drop a call to the referenced script and have my panels come and go as I would expect without needing to initiate the script manually.
Thanks!
Update: I have added a bounty of 50 (max I can do) for an answer.
Ben
I guess one of the problems listed below occures (or both):
1) looks like your xrandr snippet doesn't return proper values because the $DISPLAY environment variable is not set correctly. Acpi handler script normally runs as a user which is not the user running your current X session. That way xrandr just does not know which $DISPLAY to access.
2) if $DISPLAY is set correctly, the acpid user might still not be able to access your running xsession. You might check whether the script will work over acpi handler, if you execute xhost + as the user who is currently runging the current xsession with $DISPLAY specified in your script. This will disable access control for X. You can reenable it with xhost - again.
Check it, I hope it helps or will at least point you in which direction to dig.

Resources