如何更好地调试此间歇性/不确定性Python分段错误?

时间:2016-03-31 14:17:50

标签: python multithreading python-2.7 segmentation-fault paramiko

警告:这很长,我无法理解任何人为此做志愿者,但我真的需要解决这个问题。我将尝试提供尽可能多的信息,我非常感谢我应该去哪里调试这个。我明白当你看不到整个消息来源时它会变得无比复杂,所以我道歉,但是这个错误已经把我推倒了2天了。

在运行时仅发生大约1/7次(每次都不能重复)

(gdb) run GUI.py
Starting program: /usr/bin/python2.7 GUI.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7ffff4947700 (LWP 4868)]
[New Thread 0x7fffef655700 (LWP 4870)]
[New Thread 0x7fffeee54700 (LWP 4872)]
[Thread 0x7fffeee54700 (LWP 4872) exited]
[New Thread 0x7fffeee54700 (LWP 4874)]

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff68b416d in ?? () from /usr/lib64/libtk8.6.so
(gdb) info threads
  Id   Target Id         Frame 
  5    Thread 0x7fffeee54700 (LWP 4874) "python2.7" 0x00007ffff781c0af in pthread_cond_wait@@GLIBC_2.3.2 ()
   from /lib64/libpthread.so.0
  3    Thread 0x7fffef655700 (LWP 4870) "python2.7" 0x00007ffff754006d in poll () from /lib64/libc.so.6
  2    Thread 0x7ffff4947700 (LWP 4868) "python2.7" 0x00007ffff7541e43 in select () from /lib64/libc.so.6
* 1    Thread 0x7ffff7fd1700 (LWP 4867) "python2.7" 0x00007ffff68b416d in ?? () from /usr/lib64/libtk8.6.so
(gdb) l
1 ../sysdeps/x86_64/crti.S: No such file or directory.
(gdb) backtrace 
#0  0x00007ffff68b416d in ?? () from /usr/lib64/libtk8.6.so
#1  0x00007ffff6553ce6 in TclServiceIdle () from /usr/lib64/libtcl8.6.so
#2  0x00007ffff6534d0d in Tcl_DoOneEvent () from /usr/lib64/libtcl8.6.so
#3  0x00007ffff6b4ede0 in ?? () from /usr/lib64/python2.7/lib-dynload/_tkinter.so
#4  0x00007ffff7af5bc3 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#5  0x00007ffff7afbae6 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0
#6  0x00007ffff7af55d3 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#7  0x00007ffff7af732c in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#8  0x00007ffff7afbae6 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0
#9  0x00007ffff7b28802 in PyEval_EvalCode () from /usr/lib64/libpython2.7.so.1.0
#10 0x00007ffff7b34f6d in ?? () from /usr/lib64/libpython2.7.so.1.0
#11 0x00007ffff7ac3005 in PyRun_FileExFlags () from /usr/lib64/libpython2.7.so.1.0
#12 0x00007ffff7ac3be4 in PyRun_SimpleFileExFlags () from /usr/lib64/libpython2.7.so.1.0
#13 0x00007ffff7acb813 in Py_Main () from /usr/lib64/libpython2.7.so.1.0
#14 0x00007ffff7483be5 in __libc_start_main () from /lib64/libc.so.6
#15 0x0000000000400791 in _start ()

我的代码是2,500多行,所以我尽可能地减少了解释发生了什么。我省略了init部分,因此请忽略来自剪切的任何语法错误。

class SSH:
        # Function call can specify if stdout/err is to be omitted
    def sshRunCommand(self, command, print_stdout=True, print_stderr=True):

        # Appends command to always change to the home directory first
        x = "cd /home/" + self.username + "/; " + command

        # Locally output an terminal-esque command look-a-like
        if print_stdout:
            print self.username + "@" + self.payloadd + ":" + x

        # Execute the command storing input/output to local variables
        try:
            (stdin, stdout, stderr) = self.client.exec_command(x)
        except Exception as e:
            tkMessageBox.showerror("Error", e)
            return ([], [])
        return (stdout, stderr)

class GUI:
    def __init__(self):
        self.ssh_session = SSH()

    def uploadThreadStart(self):
        global q

        # Code here just SFTPs file, never causes error


        # If user wants to load image into local registry, do so.
        try:
            if tkMessageBox.askyesno("Load Image?",
            "Would you like to load the image on remote PC?"):
                q.put("sftp.load")
                self.ssh_session.sshRunCommand(
                    "docker load --input " +
                    os.path.basename(self.m_file.name),
                    True, True)
                print "Successfully loaded image " + self.m_file.name
            q.put("sftp.complete")
        except Exception as e:
            tkMessageBox.showerror("Error", e)

    # Function call for actually uploading Container
    def uploadDockerImagePopupWindowButtonPressed(self):
        global sftp_thread
        global q

        # Start the thread
        if self.m_file:
            q.put("sftp.start")
            sftp_thread = Thread(
                target=self.uploadThreadStart,
                args=())
            sftp_thread.daemon = True
            sftp_thread.start()
        return

这很简单:GUI是主线程,如果按下按钮,则会启动一个新线程,其中输入字段中的文件(例如/home/user/file.tar)被分配给self.m_file并且sftp结束了。 Paramiko似乎总是产生一个单独的线程来做这件事(来自gdb输出)。然后我提示使用Paramiko运行exec_command,如果他们想要“加载”他们刚刚转移的文件。我总是以cd /home/user/开头。我被引导相信,因为sshRunCommand中的打印语句没有显示,分段错误发生在exec_command.附近

这里有什么明显的东西或者是为了解决这个问题吗?多线程似乎是一种竞争条件,但我非常不确定。如果你读过这本书,甚至是略读它,我非常感谢你的时间。

0 个答案:

没有答案
相关问题
最新问题