summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml1
-rw-r--r--changes/bug301875
-rw-r--r--changes/ticket321783
-rw-r--r--configure.ac8
-rw-r--r--src/core/or/include.am1
-rw-r--r--src/feature/control/control_events.c26
-rw-r--r--src/feature/control/control_events.h2
-rw-r--r--src/lib/thread/compat_winthreads.c124
-rw-r--r--src/lib/thread/threads.h7
-rw-r--r--src/test/test_controller_events.c28
10 files changed, 104 insertions, 101 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ba61c71b2b..a672d8ed39 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -170,6 +170,7 @@ debian-tracing:
variables:
TRACING: "yes"
CHECK: "no"
+ DISTCHECK: "yes"
script:
- ./scripts/ci/ci-driver.sh
# Ensure that we only run tracing when it's implemented.
diff --git a/changes/bug30187 b/changes/bug30187
new file mode 100644
index 0000000000..2a3358d6be
--- /dev/null
+++ b/changes/bug30187
@@ -0,0 +1,5 @@
+ o Major bugfixes (relay, windows):
+ - Fix bug where running a relay on Windows would use 100%
+ CPU after some time. Makes Windows >= Vista the required
+ Windows version to build and run tor. Fixes bug 30187;
+ bugfix on 0.4.5.1-alpha. Patch by Daniel Pinto.
diff --git a/changes/ticket32178 b/changes/ticket32178
new file mode 100644
index 0000000000..c13e490cb0
--- /dev/null
+++ b/changes/ticket32178
@@ -0,0 +1,3 @@
+ o Minor bugfixes (logging):
+ - Remove trailing whitespaces from control event log messages. Fixes bug
+ 32178; bugfix on 0.1.1.1-alpha. Based on a patch by Amadeusz Pawlik.
diff --git a/configure.ac b/configure.ac
index 8bb6e6bbde..5e16884f74 100644
--- a/configure.ac
+++ b/configure.ac
@@ -574,14 +574,14 @@ fi
AH_BOTTOM([
#ifdef _WIN32
-/* Defined to access windows functions and definitions for >=WinXP */
+/* Defined to access windows functions and definitions for >=WinVista */
# ifndef WINVER
-# define WINVER 0x0501
+# define WINVER 0x0600
# endif
-/* Defined to access _other_ windows functions and definitions for >=WinXP */
+/* Defined to access _other_ windows functions and definitions for >=WinVista */
# ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0501
+# define _WIN32_WINNT 0x0600
# endif
/* Defined to avoid including some windows headers as part of Windows.h */
diff --git a/src/core/or/include.am b/src/core/or/include.am
index 9ff92adbde..7c42268c46 100644
--- a/src/core/or/include.am
+++ b/src/core/or/include.am
@@ -71,6 +71,7 @@ noinst_HEADERS += \
src/core/or/entry_port_cfg_st.h \
src/core/or/extend_info_st.h \
src/core/or/listener_connection_st.h \
+ src/core/or/lttng_circuit.inc \
src/core/or/onion.h \
src/core/or/or.h \
src/core/or/or_periodic.h \
diff --git a/src/feature/control/control_events.c b/src/feature/control/control_events.c
index 2970745ca0..0dd52659ec 100644
--- a/src/feature/control/control_events.c
+++ b/src/feature/control/control_events.c
@@ -1352,6 +1352,27 @@ enable_control_logging(void)
tor_assert(0);
}
+/** Remove newline and carriage-return characters from @a msg, replacing them
+ * with spaces, and discarding any that appear at the end of the message */
+void
+control_logmsg_strip_newlines(char *msg)
+{
+ char *cp;
+ for (cp = msg; *cp; ++cp) {
+ if (*cp == '\r' || *cp == '\n') {
+ *cp = ' ';
+ }
+ }
+ if (cp == msg)
+ return;
+ /* Remove trailing spaces */
+ for (--cp; *cp == ' '; --cp) {
+ *cp = '\0';
+ if (cp == msg)
+ break;
+ }
+}
+
/** We got a log message: tell any interested control connections. */
void
control_event_logmsg(int severity, log_domain_mask_t domain, const char *msg)
@@ -1380,11 +1401,8 @@ control_event_logmsg(int severity, log_domain_mask_t domain, const char *msg)
char *b = NULL;
const char *s;
if (strchr(msg, '\n')) {
- char *cp;
b = tor_strdup(msg);
- for (cp = b; *cp; ++cp)
- if (*cp == '\r' || *cp == '\n')
- *cp = ' ';
+ control_logmsg_strip_newlines(b);
}
switch (severity) {
case LOG_DEBUG: s = "DEBUG"; break;
diff --git a/src/feature/control/control_events.h b/src/feature/control/control_events.h
index 6e3cfef4e9..0ac233cc6e 100644
--- a/src/feature/control/control_events.h
+++ b/src/feature/control/control_events.h
@@ -341,6 +341,8 @@ struct control_event_t {
extern const struct control_event_t control_event_table[];
+void control_logmsg_strip_newlines(char *msg);
+
#ifdef TOR_UNIT_TESTS
MOCK_DECL(STATIC void,
send_control_event_string,(uint16_t event, const char *msg));
diff --git a/src/lib/thread/compat_winthreads.c b/src/lib/thread/compat_winthreads.c
index 2ca5620d23..fcc9c0279b 100644
--- a/src/lib/thread/compat_winthreads.c
+++ b/src/lib/thread/compat_winthreads.c
@@ -10,18 +10,32 @@
* functions.
*/
+#include "orconfig.h"
+
#ifdef _WIN32
+/* For condition variable support */
+#ifndef WINVER
+#error "orconfig.h didn't define WINVER"
+#endif
+#ifndef _WIN32_WINNT
+#error "orconfig.h didn't define _WIN32_WINNT"
+#endif
+#if WINVER < 0x0600
+#error "winver too low"
+#endif
+#if _WIN32_WINNT < 0x0600
+#error "winver too low"
+#endif
#include <windows.h>
#include <process.h>
+#include <time.h>
+
#include "lib/thread/threads.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/log/win32err.h"
-/* This value is more or less total cargo-cult */
-#define SPIN_COUNT 2000
-
/** Minimalist interface to run a void function in the background. On
* Unix calls fork, on win32 calls beginthread. Returns -1 on failure.
* func should not return, but rather should call spawn_exit.
@@ -64,45 +78,24 @@ tor_get_thread_id(void)
int
tor_cond_init(tor_cond_t *cond)
{
- memset(cond, 0, sizeof(tor_cond_t));
- if (InitializeCriticalSectionAndSpinCount(&cond->lock, SPIN_COUNT)==0) {
- return -1;
- }
- if ((cond->event = CreateEvent(NULL,TRUE,FALSE,NULL)) == NULL) {
- DeleteCriticalSection(&cond->lock);
- return -1;
- }
- cond->n_waiting = cond->n_to_wake = cond->generation = 0;
+ InitializeConditionVariable(&cond->cond);
return 0;
}
void
tor_cond_uninit(tor_cond_t *cond)
{
- DeleteCriticalSection(&cond->lock);
- CloseHandle(cond->event);
+ (void) cond;
}
-static void
-tor_cond_signal_impl(tor_cond_t *cond, int broadcast)
-{
- EnterCriticalSection(&cond->lock);
- if (broadcast)
- cond->n_to_wake = cond->n_waiting;
- else
- ++cond->n_to_wake;
- cond->generation++;
- SetEvent(cond->event);
- LeaveCriticalSection(&cond->lock);
-}
void
tor_cond_signal_one(tor_cond_t *cond)
{
- tor_cond_signal_impl(cond, 0);
+ WakeConditionVariable(&cond->cond);
}
void
tor_cond_signal_all(tor_cond_t *cond)
{
- tor_cond_signal_impl(cond, 1);
+ WakeAllConditionVariable(&cond->cond);
}
int
@@ -152,66 +145,23 @@ int
tor_cond_wait(tor_cond_t *cond, tor_mutex_t *lock_, const struct timeval *tv)
{
CRITICAL_SECTION *lock = &lock_->mutex;
- int generation_at_start;
- int waiting = 1;
- int result = -1;
- DWORD ms = INFINITE, ms_orig = INFINITE, startTime, endTime;
- if (tv)
- ms_orig = ms = tv->tv_sec*1000 + (tv->tv_usec+999)/1000;
-
- EnterCriticalSection(&cond->lock);
- ++cond->n_waiting;
- generation_at_start = cond->generation;
- LeaveCriticalSection(&cond->lock);
-
- LeaveCriticalSection(lock);
-
- startTime = GetTickCount();
- do {
- DWORD res;
- res = WaitForSingleObject(cond->event, ms);
- EnterCriticalSection(&cond->lock);
- if (cond->n_to_wake &&
- cond->generation != generation_at_start) {
- --cond->n_to_wake;
- --cond->n_waiting;
- result = 0;
- waiting = 0;
- goto out;
- } else if (res != WAIT_OBJECT_0) {
- result = (res==WAIT_TIMEOUT) ? 1 : -1;
- --cond->n_waiting;
- waiting = 0;
- goto out;
- } else if (ms != INFINITE) {
- endTime = GetTickCount();
- if (startTime + ms_orig <= endTime) {
- result = 1; /* Timeout */
- --cond->n_waiting;
- waiting = 0;
- goto out;
- } else {
- ms = startTime + ms_orig - endTime;
- }
- }
- /* If we make it here, we are still waiting. */
- if (cond->n_to_wake == 0) {
- /* There is nobody else who should wake up; reset
- * the event. */
- ResetEvent(cond->event);
- }
- out:
- LeaveCriticalSection(&cond->lock);
- } while (waiting);
-
- EnterCriticalSection(lock);
-
- EnterCriticalSection(&cond->lock);
- if (!cond->n_waiting)
- ResetEvent(cond->event);
- LeaveCriticalSection(&cond->lock);
+ DWORD ms = INFINITE;
+ if (tv) {
+ ms = tv->tv_sec*1000 + (tv->tv_usec+999)/1000;
+ }
- return result;
+ BOOL ok = SleepConditionVariableCS(&cond->cond, lock, ms);
+ if (!ok) {
+ DWORD err = GetLastError();
+ if (err == ERROR_TIMEOUT) {
+ return 1;
+ }
+ char *msg = format_win32_error(err);
+ log_err(LD_GENERAL, "Error waiting for condition variable: %s", msg);
+ tor_free(msg);
+ return -1;
+ }
+ return 0;
}
void
diff --git a/src/lib/thread/threads.h b/src/lib/thread/threads.h
index fcc0c23a87..ead4dc3874 100644
--- a/src/lib/thread/threads.h
+++ b/src/lib/thread/threads.h
@@ -42,12 +42,7 @@ typedef struct tor_cond_t {
#ifdef USE_PTHREADS
pthread_cond_t cond;
#elif defined(USE_WIN32_THREADS)
- HANDLE event;
-
- CRITICAL_SECTION lock;
- int n_waiting;
- int n_to_wake;
- int generation;
+ CONDITION_VARIABLE cond;
#else
#error no known condition implementation.
#endif /* defined(USE_PTHREADS) || ... */
diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c
index 60dfbd630a..3cd529fa10 100644
--- a/src/test/test_controller_events.c
+++ b/src/test/test_controller_events.c
@@ -437,6 +437,33 @@ test_cntev_signal(void *arg)
}
static void
+test_cntev_log_fmt(void *arg)
+{
+ (void) arg;
+ char *result = NULL;
+#define CHECK(pre, post) \
+ do { \
+ result = tor_strdup((pre)); \
+ control_logmsg_strip_newlines(result); \
+ tt_str_op(result, OP_EQ, (post)); \
+ tor_free(result); \
+ } while (0)
+
+ CHECK("There is a ", "There is a");
+ CHECK("hello", "hello");
+ CHECK("", "");
+ CHECK("Put spaces at the end ", "Put spaces at the end");
+ CHECK(" ", "");
+ CHECK("\n\n\n", "");
+ CHECK("Testing\r\n", "Testing");
+ CHECK("T e s t\ni n g\n", "T e s t i n g");
+
+ done:
+ tor_free(result);
+#undef CHECK
+}
+
+static void
setup_orconn_state(orconn_state_msg_t *msg, uint64_t gid, uint64_t chan,
int proxy_type)
{
@@ -718,6 +745,7 @@ struct testcase_t controller_event_tests[] = {
TEST(event_mask, TT_FORK),
TEST(format_stream, TT_FORK),
TEST(signal, TT_FORK),
+ TEST(log_fmt, 0),
T_PUBSUB(dirboot_defer_desc, TT_FORK),
T_PUBSUB(dirboot_defer_orconn, TT_FORK),
T_PUBSUB(orconn_state, TT_FORK),