Sporadically crashes on Windows when exit. Fixes #3177
1) Shutdown the python server properly. 2) Disabled "Shutdown server" menu till server is not successfully started. Initial patch sent by Maxim, modified by Akshay Joshi.pull/9/head
parent
3c4359270e
commit
54b1a79cb6
|
|
@ -328,3 +328,14 @@ void Server::run()
|
||||||
fclose(cp);
|
fclose(cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server::shutdown(QUrl url)
|
||||||
|
{
|
||||||
|
bool shotdown = shutdownServer(url);
|
||||||
|
if (!shotdown)
|
||||||
|
setError(tr("Failed to shutdown application server thread."));
|
||||||
|
|
||||||
|
QThread::quit();
|
||||||
|
QThread::wait();
|
||||||
|
while(!this->isFinished()){}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,9 @@ public:
|
||||||
bool Init();
|
bool Init();
|
||||||
QString getError() { return m_error; }
|
QString getError() { return m_error; }
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void shutdown(QUrl url);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,7 @@ void TrayIcon::createActions()
|
||||||
connect(m_logAction, SIGNAL(triggered()), this, SLOT(onLog()));
|
connect(m_logAction, SIGNAL(triggered()), this, SLOT(onLog()));
|
||||||
|
|
||||||
m_quitAction = new QAction(tr("&Shutdown server"), this);
|
m_quitAction = new QAction(tr("&Shutdown server"), this);
|
||||||
|
m_quitAction->setEnabled(false);
|
||||||
connect(m_quitAction, SIGNAL(triggered()), this, SLOT(onQuit()));
|
connect(m_quitAction, SIGNAL(triggered()), this, SLOT(onQuit()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -239,6 +240,16 @@ void TrayIcon::onQuit()
|
||||||
{
|
{
|
||||||
if (QMessageBox::Yes == QMessageBox::question(this, tr("Shutdown server?"), QString(tr("Are you sure you want to shutdown the %1 server?")).arg(PGA_APP_NAME), QMessageBox::Yes | QMessageBox::No))
|
if (QMessageBox::Yes == QMessageBox::question(this, tr("Shutdown server?"), QString(tr("Are you sure you want to shutdown the %1 server?")).arg(PGA_APP_NAME), QMessageBox::Yes | QMessageBox::No))
|
||||||
{
|
{
|
||||||
|
// Emit the signal to shutdown the python server.
|
||||||
|
emit shutdownSignal(m_appServerUrl);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrayIcon::enableShutdownMenu()
|
||||||
|
{
|
||||||
|
if (m_quitAction != NULL)
|
||||||
|
{
|
||||||
|
m_quitAction->setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ public:
|
||||||
|
|
||||||
bool Init();
|
bool Init();
|
||||||
void setAppServerUrl(QString appServerUrl);
|
void setAppServerUrl(QString appServerUrl);
|
||||||
|
void enableShutdownMenu();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createTrayIcon();
|
void createTrayIcon();
|
||||||
|
|
@ -56,6 +57,9 @@ private slots:
|
||||||
void onConfig();
|
void onConfig();
|
||||||
void onLog();
|
void onLog();
|
||||||
void onQuit();
|
void onQuit();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void shutdownSignal(QUrl);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TRAYICON_H
|
#endif // TRAYICON_H
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,7 @@ int main(int argc, char * argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QObject::connect(server, SIGNAL(finished()), server, SLOT(deleteLater()));
|
||||||
server->start();
|
server->start();
|
||||||
|
|
||||||
// This is a hack to give the server a chance to start and potentially fail. As
|
// This is a hack to give the server a chance to start and potentially fail. As
|
||||||
|
|
@ -336,6 +337,8 @@ int main(int argc, char * argv[])
|
||||||
|
|
||||||
// Go!
|
// Go!
|
||||||
trayicon->setAppServerUrl(appServerUrl);
|
trayicon->setAppServerUrl(appServerUrl);
|
||||||
|
// Enable the shutdown server menu as server started successfully.
|
||||||
|
trayicon->enableShutdownMenu();
|
||||||
|
|
||||||
QString cmd = settings.value("BrowserCommand").toString();
|
QString cmd = settings.value("BrowserCommand").toString();
|
||||||
|
|
||||||
|
|
@ -355,6 +358,8 @@ int main(int argc, char * argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QObject::connect(trayicon, SIGNAL(shutdownSignal(QUrl)), server, SLOT(shutdown(QUrl)));
|
||||||
|
|
||||||
splash->finish(NULL);
|
splash->finish(NULL);
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
|
@ -435,3 +440,44 @@ unsigned long sdbm(unsigned char *str)
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown the application server
|
||||||
|
bool shutdownServer(QUrl url)
|
||||||
|
{
|
||||||
|
QNetworkAccessManager manager;
|
||||||
|
QEventLoop loop;
|
||||||
|
QNetworkReply *reply;
|
||||||
|
QVariant redirectUrl;
|
||||||
|
|
||||||
|
url.setPath("/misc/shutdown");
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
reply = manager.get(QNetworkRequest(url));
|
||||||
|
|
||||||
|
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||||
|
loop.exec();
|
||||||
|
|
||||||
|
redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||||
|
url = redirectUrl.toUrl();
|
||||||
|
|
||||||
|
if (!redirectUrl.isNull())
|
||||||
|
delete reply;
|
||||||
|
|
||||||
|
} while (!redirectUrl.isNull());
|
||||||
|
|
||||||
|
if (reply->error() != QNetworkReply::NoError)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString response = reply->readAll();
|
||||||
|
|
||||||
|
if (response != "SHUTDOWN")
|
||||||
|
{
|
||||||
|
qDebug() << "Failed to connect, server response: " << response;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,5 +39,6 @@ bool PingServer(QUrl url);
|
||||||
void delay(int milliseconds);
|
void delay(int milliseconds);
|
||||||
void cleanup();
|
void cleanup();
|
||||||
unsigned long sdbm(unsigned char *str);
|
unsigned long sdbm(unsigned char *str);
|
||||||
|
bool shutdownServer(QUrl url);
|
||||||
|
|
||||||
#endif // PGADMIN4_H
|
#endif // PGADMIN4_H
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
"""A blueprint module providing utility functions for the application."""
|
"""A blueprint module providing utility functions for the application."""
|
||||||
|
|
||||||
import pgadmin.utils.driver as driver
|
import pgadmin.utils.driver as driver
|
||||||
from flask import url_for, render_template, Response
|
from flask import url_for, render_template, Response, request
|
||||||
from flask_babel import gettext
|
from flask_babel import gettext
|
||||||
from pgadmin.utils import PgAdminModule
|
from pgadmin.utils import PgAdminModule
|
||||||
from pgadmin.utils.preferences import Preferences
|
from pgadmin.utils.preferences import Preferences
|
||||||
|
|
@ -116,3 +116,17 @@ def explain_js():
|
||||||
status=200,
|
status=200,
|
||||||
mimetype="application/javascript"
|
mimetype="application/javascript"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# A special URL used to shutdown the server
|
||||||
|
##########################################################################
|
||||||
|
@blueprint.route("/shutdown", methods=('get', 'post'))
|
||||||
|
def shutdown():
|
||||||
|
if config.SERVER_MODE is not True:
|
||||||
|
func = request.environ.get('werkzeug.server.shutdown')
|
||||||
|
if func is None:
|
||||||
|
raise RuntimeError('Not running with the Werkzeug Server')
|
||||||
|
func()
|
||||||
|
return 'SHUTDOWN'
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue