commit e428847150a282aa107b0ba173f3956453810eb4 Author: Tomas Touceda chiiph@gentoo.org Date: Fri Apr 22 01:02:21 2011 -0300
Another approach to the Control Password problem
- Tries kills only the tor process that's listening to the ControlPort specified in the config. - Doesn't ask for password anymore. Now it displays nice messages, courtesy of nickm (thanks!).
- Fixes problem with saving advanced settings when Vidalia isn't running Tor because the instance got "zombied" in another Vidalia run&crash. --- src/common/procutil.cpp | 66 ++++++++++++++++++++++++++--- src/common/procutil.h | 3 +- src/vidalia/ControlPasswordInputDialog.ui | 15 +++---- src/vidalia/MainWindow.cpp | 10 ++--- src/vidalia/config/AdvancedPage.cpp | 3 +- 5 files changed, 74 insertions(+), 23 deletions(-)
diff --git a/src/common/procutil.cpp b/src/common/procutil.cpp index c2fbbc4..cad0add 100644 --- a/src/common/procutil.cpp +++ b/src/common/procutil.cpp @@ -21,6 +21,11 @@ #include <QFileInfo> #include <QTextStream> #include <QApplication> +#include <QProcess> + +#if !defined(Q_OS_WIN) +#include <signal.h> +#endif
/** Returns the PID of the current process. */ @@ -104,13 +109,9 @@ read_pidfile(const QString &pidFileName, QString *errmsg) }
QHash<qint64, QString> -process_list() +process_list(quint16 port) { -#if defined(Q_OS_WIN32) - return win32_process_list(); -#else - return QHash<qint64, QString>(); -#endif + return universal_process_list(port); }
bool @@ -127,7 +128,60 @@ process_kill(qint64 pid)
return (ret != FALSE); #else + if(!kill(pid, 15)) + return true; return false; #endif }
+QHash<qint64, QString> +universal_process_list(quint16 port) +{ + QHash<qint64, QString> pl; + + QProcess ps; + QStringList args; +#if defined(Q_OS_LINUX) + args << "-npl"; +#else + args << "-no"; +#endif + + ps.start("netstat", args, QIODevice::ReadOnly); + while(!ps.waitForFinished()); + + QString flt = QString("127.0.0.1:%1").arg(port); + QStringList lines = QString(ps.readAllStandardOutput()).split("\n"); + QStringList filtered = lines.filter(flt); + +#if defined(Q_OS_WIN) + filtered = filtered.filter("LISTENING"); +#endif + + if(filtered.length() == 0) + return QHash<qint64, QString>(); + + qint64 pid = 0; + QString proc = ""; +#if defined(Q_OS_LINUX) + foreach(QString line, lines) { + QStringList items = line.trimmed().split(" "); + if(items.length() < 1) + continue; + items = items.last().trimmed().split("/"); + if(items.length() < 2) + continue; + + pid = items[0].toLong(); + proc = items[1]; + + pl.insert(pid, proc); + } +#else + pid = filtered[0].split(" ").last().trimmed().toLong(); + proc = "tor"; + pl.insert(pid, proc); +#endif + + return pl; +} diff --git a/src/common/procutil.h b/src/common/procutil.h index 7e9b7dc..537fda0 100644 --- a/src/common/procutil.h +++ b/src/common/procutil.h @@ -45,7 +45,8 @@ qint64 read_pidfile(const QString &pidfile, QString *errmsg = 0);
/** Return a list of all currently running PIDs and their associated process * names. */ -QHash<qint64, QString> process_list(); +QHash<qint64, QString> process_list(quint16 port = 0); +QHash<qint64, QString> universal_process_list(quint16 port);
/** Attempt to kill process <b>pid</b>. Return true if the specified process * was successfully terminated. Otherwise, return false. */ diff --git a/src/vidalia/ControlPasswordInputDialog.ui b/src/vidalia/ControlPasswordInputDialog.ui index 0b51081..07b761c 100644 --- a/src/vidalia/ControlPasswordInputDialog.ui +++ b/src/vidalia/ControlPasswordInputDialog.ui @@ -9,7 +9,7 @@ <rect> <x>0</x> <y>0</y> - <width>356</width> + <width>470</width> <height>189</height> </rect> </property> @@ -59,7 +59,9 @@ </size> </property> <property name="text"> - <string>Vidalia has detected that there is a Tor running, probably launched by another Vidalia instance.</string> + <string>Tor is already running, but Vidalia can't connect to it. + +This can happen when something else (such as another active Vidalia process, or a Vidalia process that crashed) launched Tor.</string> </property> <property name="textFormat"> <enum>Qt::PlainText</enum> @@ -97,9 +99,7 @@ <number>1</number> </property> <property name="text"> - <string>Vidalia is unable to connect to it. -You could: -* Exit Vidalia, and try to kill the running Tor instance.</string> + <string>You will need to shut down the Tor process before Vidalia can launch a new one. </string> </property> <property name="textFormat"> <enum>Qt::AutoText</enum> @@ -124,10 +124,7 @@ You could: </sizepolicy> </property> <property name="text"> - <string>Vidalia is unable to connect to it. -You could: -* Exit Vidalia, or -* Press Reset to try to restart Tor.</string> + <string>Vidalia can try to restart Tor for you. Doing so will close all currently active connections through your Tor process.</string> </property> <property name="wordWrap"> <bool>true</bool> diff --git a/src/vidalia/MainWindow.cpp b/src/vidalia/MainWindow.cpp index 84849b6..db28916 100644 --- a/src/vidalia/MainWindow.cpp +++ b/src/vidalia/MainWindow.cpp @@ -851,18 +851,16 @@ MainWindow::authenticationFailed(QString errmsg)
qint64 torPid = 0;
-#if defined(Q_OS_WIN32) - QHash<qint64, QString> procs = process_list(); + TorSettings settings; + QHash<qint64, QString> procs = process_list(settings.getControlPort()); foreach (qint64 pid, procs.keys()) { - if (! procs.value(pid).compare("tor.exe", Qt::CaseInsensitive)) { + if (! procs.value(pid).compare("tor", Qt::CaseInsensitive)) { torPid = pid; break; } } + dlg.setResetEnabled(torPid > 0); -#else - dlg.setResetEnabled(false); -#endif
int ret = dlg.exec(); if (ret == QDialogButtonBox::Reset) { diff --git a/src/vidalia/config/AdvancedPage.cpp b/src/vidalia/config/AdvancedPage.cpp index 94c0308..3f0fc2b 100644 --- a/src/vidalia/config/AdvancedPage.cpp +++ b/src/vidalia/config/AdvancedPage.cpp @@ -165,7 +165,8 @@ AdvancedPage::save(QString &errmsg)
/* Only remember the torrc and datadir values if Vidalia started Tor, or * if the user changed the displayed values. */ - if (Vidalia::torControl()->isVidaliaRunningTor()) { + if (Vidalia::torControl()->isVidaliaRunningTor() or + not Vidalia::torControl()->isRunning()) { QString torrc = ui.lineTorConfig->text(); if (torrc != _settings->getTorrc()) { _settings->setTorrc(torrc);