Embedded Debugging - Breakpoints Not Working

106 views
Skip to first unread message

Mears

unread,
Sep 15, 2009, 12:04:50 PM9/15/09
to Winpdb
I am attaching winpdb (GUI client) to a python script running
remotely. When I set a breakpoint and exercise the code, the
application continues on without triggering the breakpoint. To ensure
I was attached to the correct thread, I placed a forever loop just
after the spot I wanted to break and ran again. The breakpoint wasn't
triggered but after pausing the thread I was attached to, the stack
trace showed that it was stuck in my for loop.

The error message it gave me was: winpdb failed to load source file ./
App/Client/GUI/PortEditorPanel.py

I thought that since it wasn't able to bring up the source when
stopping the thread that maybe breakpoints wouldn't work. The full
path to that file it was trying to open is: /home/<user>/workspace/App/
Client/GUI/PortEditorPanel.py I made sure that /home/<user>/workspace
was part of my PYTHONPATH and I launched winpdb from /home/<user>/
workspace in an effort to make the relative path to PortEditorPanel.py
valid. Unfortunately, the symptoms were the same.

Is there any way to change winpdb's working directory so relative
paths work? I have a feeling that this problem may be due to the fact
that the application is organized into packages (app is package,
client is a package, GUI is package, etc).

Nir Aides

unread,
Sep 15, 2009, 3:33:09 PM9/15/09
to win...@googlegroups.com
What version of Winpdb are you using?

Mears

unread,
Sep 15, 2009, 4:39:34 PM9/15/09
to Winpdb
Winpdb - 1.4.6
Python - 2.5.1

Running under RH EL 5.0

Nir Aides

unread,
Sep 15, 2009, 4:59:32 PM9/15/09
to win...@googlegroups.com
can you supply a minimal scenario and example script (the most trivial which still exhibits this problem) so I can try to reproduce and the problem and debug it?

(I regularly use winpdb in embedded mode remotely with RHEL with no problems :))

Thanks,
Nir

Mears

unread,
Sep 15, 2009, 6:52:33 PM9/15/09
to Winpdb
Nir,

I discovered what the issues were. The first was that I didn't
realize that I had to call rpb2.start_embedded_debugger under each
thread of the application. That was the first issue. The second
issue that took a bit more time to troubleshoot was that at the point
where the call to start embedded debugger was called, the current
working directory had changed from when the application was launched.
Once I altered the code to ensure that current working directory when
starting embedded debugger matched the working directory when starting
the application everything worked.

However, I did notice odd behavior in the "Threads" view. Even though
I attached to multiple threads, the list would would drop items from
the list when breakpoints in another thread was hit and then add them
back when breakpoints were hit in the threads that had previously
disappeared from the list.

Nir Aides

unread,
Sep 15, 2009, 9:50:59 PM9/15/09
to win...@googlegroups.com
start_embedded_debugger should only be called once and there should not be any issues with the working directory or thread views.
If possible please provide a minimal reproduction script with instructions.

Mears

unread,
Sep 16, 2009, 11:58:13 AM9/16/09
to Winpdb
Sure, I'll illustrate the both problems I described. This isn't
really anywhere close to how my production environment is set up, but
this will work to demonstrate the problems. First, the script (a
simple wx app hacked up from the wxPython demo) that I put into a
python file called wdbTest.py:

################################ BEGIN
SCRIPT################################################

import wx, wx.lib.customtreectrl as CT
import thread
import rpdb2

class MainWindow(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self,parent,wx.ID_ANY, title, size=(600, 600), pos=
(200, 200))

self.splitter_window = wx.SplitterWindow(self, -1, style=wx.SP_3D|
wx.SP_BORDER)
self.splitter_window.SetMinimumPaneSize(20)
self.left_panel = wx.Panel(self.splitter_window, -1)
self.right_panel = wx.Panel(self.splitter_window, -1)

self.tree = CT.CustomTreeCtrl(self.left_panel, 1002, pos=(0, 0),
style=wx.TR_DEFAULT_STYLE |
wx.TR_HAS_VARIABLE_ROW_HEIGHT |
wx.TR_HAS_BUTTONS |
wx.TR_FULL_ROW_HIGHLIGHT |
wx.TR_MULTIPLE |
wx.TR_EDIT_LABELS)
self.root = self.tree.AddRoot("Root Item")

offset_lists = ["Clearance Reports", "Other Offsets"]
offset_list_combo_box = wx.ComboBox(self.right_panel, -1,
choices=offset_lists)

#Sizers
offset_sizer = wx.BoxSizer(wx.VERTICAL)
offset_sizer.Add(offset_list_combo_box, 0, wx.EXPAND)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.tree, 1, wx.EXPAND)
self.left_panel.SetSizer(vbox)
vbox2 = wx.BoxSizer(wx.VERTICAL)
vbox2.Add(offset_sizer, 1, wx.EXPAND)
self.right_panel.SetSizer(vbox2)
main_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.splitter_window.SplitVertically(self.left_panel,
self.right_panel)
main_sizer.Add(self.splitter_window, 1, wx.EXPAND)
self.SetSizer(main_sizer)

self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEndLabelEdit)
self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnBeginLabelEdit)
self.Bind(wx.EVT_KEY_DOWN, self.enterpressed)
self.tree.Bind(wx.EVT_KEY_DOWN, self.enterpressed)
self.Bind(wx.EVT_KEY_DOWN, self.enterpressed, self.tree)
self.Bind(wx.EVT_COMMAND_ENTER, self.enterpressed)
self.Bind(wx.EVT_TEXT_ENTER, self.enterpressed)

self.Show(True)

def OnBeginLabelEdit(self, event):
pass
def OnEndLabelEdit(self, event):
text = self.tree.GetEditControl().GetValue()
item_being_edited = self.tree.GetSelection()
self.tree.SetItemText(item_being_edited, text)
def enterpressed(self, event):
print "pressed enter"

def attachDebugger():
rpdb2.start_embedded_debugger("harris")

def zomg():
print "oh no you didn't"


def run():
print "New Thread ID:", thread.get_ident()
app = wx.App()
frame = MainWindow(None, -1, "Test")
app.MainLoop()


def start():
print "Thread ID:", thread.get_ident()
thread.start_new_thread(run, ())


############################################END
SCRIPT#####################################################


Now that you have the script, fire up the Python interpreter. And
issue the following:
>>> import wx
>>> import wdbTest
>>> wdbTest.start()
>>> wx.CallAfter(wdbTest.attachDebugger)

At this point, the wx thread will block waiting for you to attach, so
do so with password "harris". Now that you're attached, "open source"
wdbTest.py and place a breakpoint on the print statement in function
"zomg()". Make sure you continue the thread you are attached to and
head back to the interpreter.

>>> wdbTest.zomg()

What you should see is the print statement come out immediately after
you hit enter. The breakpoint wasn't hit because we attached to the
wx thread and we are invoking that function from the interpreter's
thread. Now, issue:

>>> wx.CallAfter(wdbTest.zomg)

Now the simple GUI will hang up and you won't see the print
statement. Go over to wdbpy and confirm that the breakpoint was hit.
Here the breakpoint works because we are invoking the function on the
wx thread wdbpy attached to. Continue the thread via wdbpy. Now,
start a second debug server on the python interpreter's thread:

>>> wdbTest.attachDebugger()

You'll notice that nothing updates in wdbpy and a you don't have to
attach wdbpy to this new debug server. Now, invoke the function with
a breakpoint on the python interpreter's thread again:

>>> wdbTest.zomg()

you'll notice that the application breaks correctly this time. Once
it breaks, the "Threads" view is updated with this second thread.
Continue it and invoke zomg again using wx.CallAfter and you can
confirm that the breakpoint now works correctly for both threads.
However, you'll notice that as soon as it breaks, the python
interpreter's thread drops off from the "Threads" view.



Reply all
Reply to author
Forward
0 new messages