Repository: mindsdb/mindsdb

Issue:
Fix address already in use when running mindsdb
We need help with find and fix bug:
When you run mindsdb in console, for each interface (specified during --api argument) it needs to run the separate process. When you interrupt the main process by ctrl-c, all other processes should stop too. But sometimes it doesn't happen. We don't know why, maybe it depends on OS, or terminal, or something else. You can check it easy:
1. for your convenience create and activate venv (commands below will be slightly different on windows):
```
python3 -m venv venv
source venv/bin/activate
```
2. install mindsdb:
```
pip3 install mindsdb
```
3. run mindsdb as:
```
python3 -m mindsdb
```
by default will be stated 2 interfaces: HTTP on port 47334 and MySQL on port 47335.
4. Interrupt it by ctrl-c
5. Run mindsdb again. If you see the error 'address already in use', then well, you caught the error :)

All processes start and close in __main__.py https://github.com/mindsdb/mindsdb/blob/staging/mindsdb/__main__.py
We assume on 'ctrl-c' interrupt should be executed in close_api_gracefully function https://github.com/mindsdb/mindsdb/blob/staging/mindsdb/__main__.py#L23


Discussion:
Hi @ZoranPandovski I am getting an error that HTTP API can't start on port 47334 , although the GUI was available on   http://127.0.0.1:47334/index.html
![mindsdb](https://user-images.githubusercontent.com/31548778/96338555-9a0e9b80-10ac-11eb-981c-1350c39d879d.PNG)

But when I ran for the second time it started correctly on port 47334 
![Capture1](https://user-images.githubusercontent.com/31548778/96338604-01c4e680-10ad-11eb-9a26-342f02d506b2.PNG)

OS:  windows 10
But I did not face issue of **address already in use** on the command line when using `ctrl+c`,it closes gracefully .  It depends on OS, or terminal ,I am not sure.

@ZoranPandovski I could reproduce this by `Ctrl+Z`. `Ctrl+C` closes it gracefrully. I am running this on Ubuntu.

```(.venv) xephyr@dome:~/mindsdb$ sudo python3 -m mindsdb
S3 Datasource is not available by default. If you wish to use it, please install mindsdb_native[extra_data_sources]
SnowflakeDS Datasource is not available by default. If you wish to use it, please install mindsdb_native[snowflake]
Configuration file:
   /home/xephyr/mindsdb/etc/config.json
Storage path:
   /home/xephyr/mindsdb/var/
Versions:
 - lightwood 0.45.0
 - MindsDB_native 2.17.0
 - MindsDB 2.11.2
http API: starting...
mysql API: starting...
S3 Datasource is not available by default. If you wish to use it, please install mindsdb_native[extra_data_sources]
SnowflakeDS Datasource is not available by default. If you wish to use it, please install mindsdb_native[snowflake]
S3 Datasource is not available by default. If you wish to use it, please install mindsdb_native[extra_data_sources]
SnowflakeDS Datasource is not available by default. If you wish to use it, please install mindsdb_native[snowflake]
Process SpawnProcess-2:
Traceback (most recent call last):
  File "/usr/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/usr/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/home/xephyr/mindsdb/mindsdb/api/mysql/start.py", line 13, in start
    MysqlProxy.startProxy(config)
  File "/home/xephyr/mindsdb/mindsdb/api/mysql/mysql_proxy/mysql_proxy.py", line 1478, in startProxy
    server = SocketServer.ThreadingTCPServer((host, port), MysqlProxy)
  File "/usr/lib/python3.8/socketserver.py", line 452, in __init__
    self.server_bind()
  File "/usr/lib/python3.8/socketserver.py", line 466, in server_bind
    self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use
 - GUI available at http://127.0.0.1:47334/index.html
Process SpawnProcess-1:
Traceback (most recent call last):
  File "/usr/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/usr/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/home/xephyr/mindsdb/mindsdb/api/http/start.py", line 48, in start
    serve(app, port=port, host=host)
  File "/usr/local/lib/python3.8/dist-packages/waitress/__init__.py", line 12, in serve
    server = _server(app, **kw)
  File "/usr/local/lib/python3.8/dist-packages/waitress/server.py", line 81, in create_server
    last_serv = TcpWSGIServer(
  File "/usr/local/lib/python3.8/dist-packages/waitress/server.py", line 239, in __init__
    self.bind_server_socket()
  File "/usr/local/lib/python3.8/dist-packages/waitress/server.py", line 368, in bind_server_socket
    self.bind(sockaddr)
  File "/usr/local/lib/python3.8/dist-packages/waitress/wasyncore.py", line 398, in bind
    return self.socket.bind(addr)
OSError: [Errno 98] Address already in use
ERROR: http API cant start on 47334
ERROR: mysql API cant start on 47335```
@ZoranPandovski it happens when you use CTRL +Z. do we need to fix this for when we do CTRL+Z ?
Thanks, everyone.  So we need a fix for this. We assume on 'ctrl-c' interrupt should be executed in close_api_gracefully function https://github.com/mindsdb/mindsdb/blob/staging/mindsdb/__main__.py#L23



Resolving patch:
diff --git a/mindsdb/__main__.py b/mindsdb/__main__.py
--- a/mindsdb/__main__.py
+++ b/mindsdb/__main__.py
@@ -27,13 +27,15 @@
 
 
 def close_api_gracefully(apis):
-    for api in apis.values():
-        process = api['process']
-        sys.stdout.flush()
-        process.terminate()
-        process.join()
-        sys.stdout.flush()
-
+    try: 
+        for api in apis.values():
+            process = api['process']
+            sys.stdout.flush()
+            process.terminate()
+            process.join()
+            sys.stdout.flush()
+    except KeyboardInterrupt:
+        sys.exit(0)
 
 if __name__ == '__main__':
     version_error_msg = """


Test patch: