[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [vidalia/alpha] Make TorControl work without threads
commit a3b901fa122bc8f4b82a48d3eb3fae1fede86898
Author: Tomás Touceda <chiiph@xxxxxxxxxxxxxx>
Date: Fri Feb 24 17:13:51 2012 -0300
Make TorControl work without threads
---
src/torcontrol/ControlConnection.cpp | 98 +++++++++++-----------------------
src/torcontrol/ControlConnection.h | 3 +-
src/torcontrol/SendCommandEvent.cpp | 18 +-----
src/torcontrol/TorControl.cpp | 4 ++
src/vidalia/MainWindow.cpp | 56 +++++++++----------
5 files changed, 67 insertions(+), 112 deletions(-)
diff --git a/src/torcontrol/ControlConnection.cpp b/src/torcontrol/ControlConnection.cpp
index 365da32..21cb527 100644
--- a/src/torcontrol/ControlConnection.cpp
+++ b/src/torcontrol/ControlConnection.cpp
@@ -29,21 +29,19 @@
/** Default constructor. */
ControlConnection::ControlConnection(ControlMethod::Method method, TorEvents *events)
+ : QObject()
{
_events = events;
_status = Unset;
_sock = 0;
_sendWaiter = new SendCommandEvent::SendWaiter();
_method = method;
+ _connected = false;
}
/** Destructor. */
ControlConnection::~ControlConnection()
{
- /* Exit the event loop */
- exit();
- /* Wait for the thread to finish */
- wait();
/* Clean up after the send waiter */
delete _sendWaiter;
}
@@ -52,7 +50,7 @@ ControlConnection::~ControlConnection()
void
ControlConnection::connect(const QHostAddress &addr, quint16 port)
{
- if (isRunning()) {
+ if (_connected) {
tc::error("Bug: Tried to call ControlConnection::connect() when the "
"control thread is already running.");
return;
@@ -65,15 +63,14 @@ ControlConnection::connect(const QHostAddress &addr, quint16 port)
_connectAttempt = 0;
setStatus(Connecting);
- /* Kick off the thread in which the control socket will live */
- QThread::start();
+ run();
}
/** Connect to the specified Tor control socket interface. */
void
ControlConnection::connect(const QString &addr)
{
- if (isRunning()) {
+ if (_connected) {
tc::error("Bug: Tried to call ControlConnection::connect() when the "
"control thread is already running.");
return;
@@ -83,8 +80,7 @@ ControlConnection::connect(const QString &addr)
_connectAttempt = 0;
setStatus(Connecting);
- /* Kick off the thread in which the control socket will live */
- QThread::start();
+ run();
}
/** Attempt to establish a connection to Tor's control interface. We will try
@@ -97,7 +93,6 @@ ControlConnection::connect()
tc::debug("Connecting to Tor (Attempt %1 of %2)").arg(_connectAttempt)
.arg(MAX_CONNECT_ATTEMPTS);
- _connMutex.lock();
switch(_method) {
case ControlMethod::Socket:
_sock->connectToServer(_path);
@@ -108,15 +103,26 @@ ControlConnection::connect()
_sock->connectToHost(_addr, _port);
break;
}
- _connMutex.unlock();
}
/** Disconnect from Tor's control interface. */
void
ControlConnection::disconnect()
{
+ /** If there are any messages waiting for a response, clear them. */
+ if (_sendWaiter->status() == SendCommandEvent::SendWaiter::Waiting)
+ _sendWaiter->setResult(false, tr("Control socket is not connected."));
+
+ while (!_recvQueue.isEmpty()) {
+ ReceiveWaiter *w = _recvQueue.dequeue();
+ w->setResult(false, ControlReply(),
+ tr("Control socket is not connected."));
+
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+ }
+
setStatus(Disconnecting);
- _connMutex.lock();
+
switch(_method) {
case ControlMethod::Socket:
_sock->disconnectFromServer();
@@ -127,7 +133,11 @@ ControlConnection::disconnect()
_sock->disconnectFromHost();
break;
}
- _connMutex.unlock();
+
+ _sock->disconnect(this);
+ delete _sock;
+ delete _connectTimer;
+ _sock = 0;
}
/** Called when the control socket is connected. This method checks that the
@@ -136,6 +146,7 @@ void
ControlConnection::onConnected()
{
setStatus(Connected);
+ _connected = true;
emit connected();
}
@@ -145,8 +156,8 @@ void
ControlConnection::onDisconnected()
{
setStatus(Disconnected);
+ _connected = false;
emit disconnected();
- exit(0);
}
/** Called when the control socket encounters <b>error</b>. */
@@ -186,9 +197,9 @@ ControlConnection::onError(QAbstractSocket::SocketError error)
void
ControlConnection::cancelConnect()
{
+ _connected = false;
tc::warn("Control connection attempt cancelled.");
setStatus(Disconnected);
- exit(0);
}
/** Returns true if the control socket is connected to Tor. */
@@ -202,7 +213,6 @@ ControlConnection::isConnected()
ControlConnection::Status
ControlConnection::status()
{
- QMutexLocker locker(&_statusMutex);
return _status;
}
@@ -227,7 +237,6 @@ ControlConnection::statusString(Status status)
void
ControlConnection::setStatus(Status status)
{
- QMutexLocker locker(&_statusMutex);
tc::debug("Control connection status changed from '%1' to '%2'")
.arg(statusString(_status))
.arg(statusString(status));
@@ -242,12 +251,10 @@ ControlConnection::send(const ControlCommand &cmd,
bool result = false;
QString errstr;
- _recvMutex.lock();
if (send(cmd, &errstr)) {
/* Create and enqueue a new receive waiter */
ReceiveWaiter *w = new ReceiveWaiter();
_recvQueue.enqueue(w);
- _recvMutex.unlock();
/* Wait for and get the result, clean up, and return */
result = w->getResult(&reply, &errstr);
@@ -257,7 +264,6 @@ ControlConnection::send(const ControlCommand &cmd,
} else {
tc::error("Failed to send control command (%1): %2").arg(cmd.keyword())
.arg(errstr);
- _recvMutex.unlock();
}
if (!result && errmsg)
@@ -271,13 +277,10 @@ ControlConnection::send(const ControlCommand &cmd,
bool
ControlConnection::send(const ControlCommand &cmd, QString *errmsg)
{
- _connMutex.lock();
if (!_sock || !_sock->isConnected()) {
- _connMutex.unlock();
return err(errmsg, tr("Control socket is not connected."));
}
QCoreApplication::postEvent(_sock, new SendCommandEvent(cmd, _sendWaiter));
- _connMutex.unlock();
return _sendWaiter->getResult(errmsg);
}
@@ -286,7 +289,6 @@ ControlConnection::send(const ControlCommand &cmd, QString *errmsg)
void
ControlConnection::onReadyRead()
{
- QMutexLocker locker(&_connMutex);
ReceiveWaiter *waiter;
QString errmsg;
@@ -304,12 +306,10 @@ ControlConnection::onReadyRead()
/* Response to a previous command */
tc::debug("Control Reply: %1").arg(reply.toString());
- _recvMutex.lock();
if (!_recvQueue.isEmpty()) {
waiter = _recvQueue.dequeue();
waiter->setResult(true, reply);
}
- _recvMutex.unlock();
}
} else {
tc::error("Unable to read control reply: %1").arg(errmsg);
@@ -323,7 +323,6 @@ void
ControlConnection::run()
{
/* Create a new control socket */
- _connMutex.lock();
_sock = new ControlSocket(_method);
_connectTimer = new QTimer();
@@ -341,33 +340,8 @@ ControlConnection::run()
QObject::connect(_connectTimer, SIGNAL(timeout()), this, SLOT(connect()),
Qt::DirectConnection);
- _connMutex.unlock();
-
/* Attempt to connect to Tor */
connect();
- tc::debug("Starting control connection event loop.");
- exec();
- tc::debug("Exited control connection event loop.");
-
- /* Clean up the socket */
- _connMutex.lock();
- _sock->disconnect(this);
- delete _sock;
- delete _connectTimer;
- _sock = 0;
- _connMutex.unlock();
-
- /* If there are any messages waiting for a response, clear them. */
- if (_sendWaiter->status() == SendCommandEvent::SendWaiter::Waiting)
- _sendWaiter->setResult(false, tr("Control socket is not connected."));
-
- _recvMutex.lock();
- while (!_recvQueue.isEmpty()) {
- ReceiveWaiter *w = _recvQueue.dequeue();
- w->setResult(false, ControlReply(),
- tr("Control socket is not connected."));
- }
- _recvMutex.unlock();
}
@@ -379,16 +353,9 @@ bool
ControlConnection::ReceiveWaiter::getResult(ControlReply *reply,
QString *errmsg)
{
- forever {
- _mutex.lock();
- if (_status == Waiting) {
- _waitCond.wait(&_mutex);
- _mutex.unlock();
- } else {
- _mutex.unlock();
- break;
- }
- }
+ while(_status == Waiting)
+ QCoreApplication::processEvents();
+
if (errmsg) {
*errmsg = _errmsg;
}
@@ -402,11 +369,8 @@ ControlConnection::ReceiveWaiter::setResult(bool success,
const ControlReply &reply,
const QString &errmsg)
{
- _mutex.lock();
_status = (success ? Success : Failed);
- _reply = reply;
+ _reply = reply;
_errmsg = errmsg;
- _mutex.unlock();
- _waitCond.wakeAll();
}
diff --git a/src/torcontrol/ControlConnection.h b/src/torcontrol/ControlConnection.h
index 5a56ced..d2d2965 100644
--- a/src/torcontrol/ControlConnection.h
+++ b/src/torcontrol/ControlConnection.h
@@ -29,7 +29,7 @@
#include <QHostAddress>
-class ControlConnection : public QThread
+class ControlConnection : public QObject
{
Q_OBJECT
@@ -127,6 +127,7 @@ private:
};
QQueue<ReceiveWaiter *> _recvQueue; /**< Objects waiting for a reply. */
SendCommandEvent::SendWaiter* _sendWaiter;
+ bool _connected;
};
#endif
diff --git a/src/torcontrol/SendCommandEvent.cpp b/src/torcontrol/SendCommandEvent.cpp
index 8472324..cf66a1a 100644
--- a/src/torcontrol/SendCommandEvent.cpp
+++ b/src/torcontrol/SendCommandEvent.cpp
@@ -16,8 +16,7 @@
#include "SendCommandEvent.h"
-#include <QMutexLocker>
-
+#include <QCoreApplication>
SendCommandEvent::SendCommandEvent(const ControlCommand &cmd, SendWaiter *w)
: QEvent(QEvent::User)
@@ -30,26 +29,16 @@ SendCommandEvent::SendCommandEvent(const ControlCommand &cmd, SendWaiter *w)
void
SendCommandEvent::SendWaiter::setResult(bool success, const QString &errmsg)
{
- _mutex.lock();
_status = (success ? Success : Failed);
_errmsg = errmsg;
- _mutex.unlock();
- _waitCond.wakeAll();
}
/** Waits for and gets the result of the send operation. */
bool
SendCommandEvent::SendWaiter::getResult(QString *errmsg)
{
- forever {
- _mutex.lock();
- if (_status == Waiting) {
- _waitCond.wait(&_mutex);
- _mutex.unlock();
- } else {
- _mutex.unlock();
- break;
- }
+ while(_status == Waiting) {
+ QCoreApplication::processEvents();
}
if (errmsg) {
*errmsg = _errmsg;
@@ -61,6 +50,5 @@ SendCommandEvent::SendWaiter::getResult(QString *errmsg)
SendCommandEvent::SendWaiter::SenderStatus
SendCommandEvent::SendWaiter::status()
{
- QMutexLocker locker(&_mutex);
return _status;
}
diff --git a/src/torcontrol/TorControl.cpp b/src/torcontrol/TorControl.cpp
index e95f9c7..603ba94 100644
--- a/src/torcontrol/TorControl.cpp
+++ b/src/torcontrol/TorControl.cpp
@@ -101,6 +101,7 @@ TorControl::~TorControl()
if (isVidaliaRunningTor()) {
stop();
}
+ _controlConn->disconnect();
delete _controlConn;
}
@@ -132,6 +133,9 @@ TorControl::stop(QString *errmsg)
{
bool rc = false;
+ if(!errmsg)
+ errmsg = new QString();
+
if (!isVidaliaRunningTor()) {
*errmsg = tr("Vidalia has not started Tor. "
"You need to stop Tor through the interface you started it.");
diff --git a/src/vidalia/MainWindow.cpp b/src/vidalia/MainWindow.cpp
index 65e1e3c..1c4241f 100644
--- a/src/vidalia/MainWindow.cpp
+++ b/src/vidalia/MainWindow.cpp
@@ -557,7 +557,6 @@ MainWindow::aboutToQuit()
QObject::disconnect(_torControl, 0, 0, 0);
}
-
/** Attempts to start Tor. If Tor fails to start, then startFailed() will be
* called with an error message containing the reason. */
void
@@ -892,34 +891,6 @@ void
MainWindow::connected()
{
authenticate();
- if(_torControl->isVidaliaRunningTor()) {
- QString err;
- if(!_torControl->takeOwnership(&err))
- vWarn(err);
- }
-
- TorSettings settings;
- if(settings.autoControlPort()) {
- // We want to remember the ports if it's on auto
- QString control_str = "", socks_str = "";
- if(_torControl->getInfo("net/listeners/control", control_str)) {
- QStringList control_parts = control_str.split(":");
- if(control_parts.size() > 1)
- control_str = control_parts[1];
- }
- if(_torControl->getInfo("net/listeners/socks", socks_str)) {
- QStringList socks_parts = socks_str.split(":");
- if(socks_parts.size() > 1)
- socks_str = socks_parts[1];
- }
-
- _previousControlPort = control_str;
- _previousSocksPort = socks_str;
- } else {
- // Otherwise we want to clear the remembered ports
- _previousControlPort = "";
- _previousSocksPort = "";
- }
}
/** Called when the connection to the control socket fails. The reason will be
@@ -952,6 +923,29 @@ MainWindow::connectFailed(QString errmsg)
void
MainWindow::authenticated()
{
+ TorSettings settings;
+ if(settings.autoControlPort()) {
+ // We want to remember the ports if it's on auto
+ QString control_str = "", socks_str = "";
+ if(_torControl->getInfo("net/listeners/control", control_str)) {
+ QStringList control_parts = control_str.split(":");
+ if(control_parts.size() > 1)
+ control_str = control_parts[1];
+ }
+ if(_torControl->getInfo("net/listeners/socks", socks_str)) {
+ QStringList socks_parts = socks_str.split(":");
+ if(socks_parts.size() > 1)
+ socks_str = socks_parts[1];
+ }
+
+ _previousControlPort = control_str;
+ _previousSocksPort = socks_str;
+ } else {
+ // Otherwise we want to clear the remembered ports
+ _previousControlPort = "";
+ _previousSocksPort = "";
+ }
+
ServerSettings serverSettings(_torControl);
QString errmsg;
@@ -1143,6 +1137,10 @@ MainWindow::bootstrapStatusChanged(const BootstrapStatus &bs)
case BootstrapStatus::BootstrappingDone:
description = tr("Connected to the Tor network!");
warn = false; /* probably false anyway */
+ // There could be a condition where the circuitEstablished
+ // signal is not emitted, so we want to assure that the green
+ // onion appears at the end
+ circuitEstablished();
break;
default:
description = tr("Unrecognized startup status");
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits