Repository: spyder-ide/spyder

Issue:
Spyder crashes when killing the current process to start a new one
## Description of your problem

**What steps will reproduce the problem?**

1. Configure run settings to 
	-Execute in a new dedicated Python console
	-Checkmark Show warning when killing running process

2. Run a script and keep it running
3. Run the same script again and click Yes on the prompt to kill the current running process

**Please provide any additional information below**
It may take a few attempts to crash but will consistently crash in under 5 attempts.


## Versions and main components

* Spyder Version: 3.1.2
* Python Version: 2.7.10
* Operating system: Windows 10 64-bit


## Dependencies

jedi >=0.8.1     :  0.9.0 (OK)
matplotlib >=1.0 :  1.4.3 (OK)
nbconvert >=4.0  :  5.1.1 (OK)
numpy >=1.7      :  1.9.2 (OK)
pandas >=0.13.1  :  0.16.2 (OK)
pep8 >=0.6       :  1.7.0 (OK)
pyflakes >=0.5.0 :  1.5.0 (OK)
pygments >=2.0   :  2.2.0 (OK)
pylint >=0.25    :  1.6.5 (OK)
qtconsole >=4.2.0:  4.2.1 (OK)
rope >=0.9.4     :  0.10.3 (OK)
sphinx >=0.6.6   :  1.5.2 (OK)
sympy >=0.7.3    :  0.7.6 (OK)


Discussion:
@dalthviz, please take a look at this one.
@ccordoba12 @andrewdam I tested the issue in the `3.1.2` version of Spyder an the following error was thrown:
```
>>> Exception in thread Thread-3:
Traceback (most recent call last):
  File "C:\Users\Daniel\Anaconda3\envs\py27\lib\threading.py", line 801, in __bootstrap_inner
    self.run()
  File "C:\Users\Daniel\Anaconda3\envs\py27\lib\site-packages\spyder\widgets\externalshell\introspection.py", line 80, in run
    self.send_socket(shell_id, conn)
  File "C:\Users\Daniel\Anaconda3\envs\py27\lib\site-packages\spyder\widgets\externalshell\introspection.py", line 56, in send_socket
    shell.set_introspection_socket(sock)
  File "C:\Users\Daniel\Anaconda3\envs\py27\lib\site-packages\spyder\widgets\externalshell\pythonshell.py", line 258, in set_introspection_socket
    'set_remote_view_settings()', settings=[settings])
  File "C:\Users\Daniel\Anaconda3\envs\py27\lib\site-packages\spyder\utils\bsdsocket.py", line 107, in communicate
    return read_packet(sock)
  File "C:\Users\Daniel\Anaconda3\envs\py27\lib\site-packages\spyder\utils\bsdsocket.py", line 65, in read_packet
    dlen, = struct.unpack("l", datalen)
error: unpack requires a string argument of length 4

```
However when I test this with the development version for `3.1.x` (`3.1.3.dev0`) no error is thrown. So, @andrewdam can you try to replicate the error but running the version in development of Spyder? Any new information in order to replicate the issue will be greatly appreciated :)
The same problem still occurs on 3.1.3.dev0
@andrewdam was there an error or any traceback thrown when you tested this?
@dalthviz I'm not sure where I'd be seeing a traceback since the application says "Python.exe has stopped working" and closes.
The same behavior is also reproducible on my system:
- Python 3.4.4
- Spyder 3.1.2 (but the problem appeared when I upgraded to 3.1.0 if I recall correctly through pip)
- PySide 1.2.2 and PyQt4 4.11.4
- Windows 7 64-bit
- Everything was installed manually through pip, not Anaconda.

Python crash systematically when re-running a script with a Qt application running, as explained by the OP. It also crash when a matplotlib figure is opened, which is coherent since I'm using the Qt backend to render the figures.

Python also crash in a similar manner when I try to navigate from one file to the other with ctrl-mouseclick.

![image](https://cloud.githubusercontent.com/assets/10170372/22521347/bdffe20e-e885-11e6-8ebb-4a2fa343a5dc.png)
@andrewdam can you please provide us the script you are re-running?, I'm trying to replicate the bug but, for now, Spyder is not crashing (I'm testing in a virtual machine with Windows 10 64 bits and Anaconda). Also, do you have a manual installation as @jnsebgosselin with pip or you are using Anaconda?.

@jnsebgosselin in your case since you have such a custom environment it is difficult to say what it is happening. However, feel free to open a new issue for each of the problems you are experimenting that, maybe related with this one, are not exactly the same (since are originated in different functionalities), and also see if for them a issue is already open. Also, thanks for the feedback :)
@dalthviz the script is just:

`raw_input("test")`

Spyder was installed using the latest version of Python(x,y) and then upgraded using pip to 3.1.2.
I've done some digging trying to narrow down the problem. Finally, Python crashes not only when re-running a script with a QApplicaton running like I was thinking. Same thing happens also by re-running in an external console the following script:

    from time import sleep
    while True:
        print('test')
        sleep(0.5)

If I replace the implementation of the QMessageBox.question dialog window in [externalconsole.py L515](https://github.com/spyder-ide/spyder/blob/master/spyder/plugins/externalconsole.py#L515) module from:

    answer = QMessageBox.question(self, self.get_plugin_title(),
        _("%s is already running in a separate process.\n"
           "Do you want to kill the process before starting "
           "a new one?") % osp.basename(fname),
        QMessageBox.Yes | QMessageBox.Cancel)`

to 

    mb = QMessageBox()
    answer = mb.question(mb, self.get_plugin_title(),
        _("%s is already running in a separate process.\n"
          "Do you want to kill the process before starting "
          "a new one?") % osp.basename(fname),
        QMessageBox.Yes | QMessageBox.Cancel)`

My Python isn't crashing anymore. So I think that by passing the `ExternalConsole` instance as parent to the question dialog window cause the problem when we kill it afterwards.

From what I understood of what I read on the forums, I think it is a behavior that is specific to PyQT4, not PyQt5. That may be why I'm experiencing this problem on my custom setup.
@andrewdam which is the version of PyQt that you are using?, can you try  if the solution of @jnsebgosselin works for you?

@jnsebgosselin thanks for looking into this 👍, if you want you can open a PR with the changes that you propose (maybe adding some kind of validation of the version of PyQt to use your change instead of the code that is now) 
@dalthviz I'm on PyQt 4.8.6. The solution of @jnsebgosselin works for me!

@jnsebgosselin Thanks!
Thanks a lot guys for helping us to narrow down the problem!! That's a great contribution from you!

@dalthviz, please make a PR based on @jnsebgosselin findings.
You are quite welcomed. Thanks for creating such a great software that has become an important part of my work. 

I think you can safely pass `self` as parent to the `QMessageBox` such as:

    mb = QMessageBox(self)

This doesn't cause my system to crash. Otherwise, the question dialog window is missing its Spyder icon.

Resolving patch:
diff --git a/spyder/plugins/externalconsole.py b/spyder/plugins/externalconsole.py
--- a/spyder/plugins/externalconsole.py
+++ b/spyder/plugins/externalconsole.py
@@ -515,11 +515,19 @@ def start(self, fname, wdir=None, args='', interact=False, debug=False,
                 if old_shell.is_running():
                     runconfig = get_run_configuration(fname)
                     if runconfig is None or runconfig.show_kill_warning:
-                        answer = QMessageBox.question(self, self.get_plugin_title(),
-                            _("%s is already running in a separate process.\n"
-                              "Do you want to kill the process before starting "
-                              "a new one?") % osp.basename(fname),
-                            QMessageBox.Yes | QMessageBox.Cancel)
+                        if PYQT5:
+                            answer = QMessageBox.question(self, self.get_plugin_title(),
+                                _("%s is already running in a separate process.\n"
+                                  "Do you want to kill the process before starting "
+                                  "a new one?") % osp.basename(fname),
+                                QMessageBox.Yes | QMessageBox.Cancel)
+                        else:
+                            mb = QMessageBox(self)
+                            answer = mb.question(mb, self.get_plugin_title(),
+                                _("%s is already running in a separate process.\n"
+                                  "Do you want to kill the process before starting "
+                                  "a new one?") % osp.basename(fname),
+                                QMessageBox.Yes | QMessageBox.Cancel)
                     else:
                         answer = QMessageBox.Yes
 


Test patch: