Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
base repository: rl1987/tor
base: master
head repository: rl1987/tor
compare: bug25245_hax
Checking mergeability… Don’t worry, you can still create the pull request.
  • 5 commits
  • 6 files changed
  • 0 comments
  • 1 contributor
Showing with 124 additions and 16 deletions.
  1. +15 −3 src/common/util_bug.c
  2. +11 −3 src/common/util_bug.h
  3. +2 −0 src/or/config.c
  4. +88 −9 src/or/connection.c
  5. +4 −0 src/or/connection.h
  6. +4 −1 src/or/or.h
@@ -67,15 +67,27 @@ tor_set_failed_assertion_callback(void (*fn)(void))
/** Helper for tor_assert: report the assertion failure. */
void
tor_assertion_failed_(const char *fname, unsigned int line,
const char *func, const char *expr)
const char *func, const char *expr,
const char *fmt, ...)
{
char buf[256];
char *extra = NULL;
va_list ap;

if (fmt) {
va_start(ap,fmt);
tor_vasprintf(&extra, fmt, ap);
va_end(ap);
}

log_err(LD_BUG, "%s:%u: %s: Assertion %s failed; aborting.",
fname, line, func, expr);
tor_snprintf(buf, sizeof(buf),
"Assertion %s failed in %s at %s:%u",
expr, func, fname, line);
"Assertion %s failed in %s at %s:%u: %s",
expr, func, fname, line, extra ? extra : "");
log_backtrace(LOG_ERR, LD_BUG, buf);

tor_free(extra);
}

/** Helper for tor_assert_nonfatal: report the assertion failure. */
@@ -62,12 +62,19 @@
#define tor_assert(a) STMT_BEGIN \
(void)(a); \
STMT_END
#define tor_assertf(a, fmt, ...) STMT_BEGIN \
(void)(a); \
(void)(fmt); \
STMT_END
#else
/** Like assert(3), but send assertion failures to the log as well as to
* stderr. */
#define tor_assert(expr) STMT_BEGIN \
#define tor_assert(expr) tor_assertf(expr, NULL)

#define tor_assertf(expr, fmt, ...) STMT_BEGIN \
if (PREDICT_UNLIKELY(!(expr))) { \
tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, #expr); \
tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, #expr, \
fmt, ##__VA_ARGS__); \
abort(); \
} STMT_END
#endif /* defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS) */
@@ -186,7 +193,8 @@ extern int bug_macro_deadcode_dummy__;
#define tor_fragile_assert() tor_assert_nonfatal_unreached_once()

void tor_assertion_failed_(const char *fname, unsigned int line,
const char *func, const char *expr);
const char *func, const char *expr,
const char *fmt, ...);
void tor_bug_occurred_(const char *fname, unsigned int line,
const char *func, const char *expr,
int once);
@@ -1611,6 +1611,8 @@ options_act_reversible(const or_options_t *old_options, char **msg)

SMARTLIST_FOREACH(replaced_listeners, connection_t *, conn,
{
close_child_connections(conn);

int marked = conn->marked_for_close;
log_notice(LD_NET, "Closing old %s on %s:%d",
conn_type_to_string(conn->type), conn->address, conn->port);
@@ -670,6 +670,47 @@ connection_free_minimal(connection_t *conn)
tor_free(mem);
}

/** Detach <b>conn</b> from it's parent (if any).
*/
static void
connection_detach_from_parent(connection_t *conn)
{
if (conn && conn->parent) {
connection_remove_child(conn->parent, conn);
}
}

/** Remove <b>child</b> from <b>parent</b>'s list of child connection
* and break parent-child relationship.
*/
void
connection_remove_child(connection_t *parent, connection_t *child)
{
tor_assert(parent);
tor_assert(child);

if (parent->children) {
// XXX: thread safety?
child->parent = NULL;
smartlist_remove(parent->children, child);
}
}

/** Establish parent-child relationship between <b>parent</b> and
* <b>child</b>.
*/
void
connection_add_child(connection_t *parent, connection_t *child)
{
tor_assert(parent);
tor_assert(child);

if (parent->children) {
smartlist_add(parent->children, child);
child->parent = parent;
}
}

/** Make sure <b>conn</b> isn't in any of the global conn lists; then free it.
*/
MOCK_IMPL(void,
@@ -709,6 +750,7 @@ connection_free_,(connection_t *conn))
}

connection_unregister_events(conn);
connection_detach_from_parent(conn);
connection_free_minimal(conn);
}

@@ -1427,6 +1469,9 @@ connection_listener_new(const struct sockaddr *listensockaddr,
*/
connection_check_oos(get_n_open_sockets(), 0);

conn->children = smartlist_new();
conn->parent = NULL;

return conn;

err:
@@ -1665,6 +1710,8 @@ connection_handle_listener_read(connection_t *conn, int new_type)
return 0; /* no need to tear down the parent */
}

connection_add_child(conn, newconn);

if (connection_init_accepted_conn(newconn, TO_LISTENER_CONN(conn)) < 0) {
if (! newconn->marked_for_close)
connection_mark_for_close(newconn);
@@ -2683,6 +2730,22 @@ retry_listener_ports(smartlist_t *old_conns,
return r;
}

/** Close and remove all child connections that belong to <b>conn</b>.
*/
void
close_child_connections(connection_t *conn)
{
if (conn->children == NULL)
return;

SMARTLIST_FOREACH_BEGIN(conn->children, connection_t *, child_conn) {
connection_close_immediate(child_conn);
connection_mark_for_close(child_conn);

smartlist_remove(conn->children, child_conn);
} SMARTLIST_FOREACH_END(child_conn);
}

/** Launch listeners for each port you should have open. Only launch
* listeners who are not already open, and only close listeners we no longer
* want.
@@ -2724,6 +2787,8 @@ retry_all_listeners(smartlist_t *replaced_conns,
if (replaced_conns) {
smartlist_add(replaced_conns, conn);
} else {
close_child_connections(conn);

connection_close_immediate(conn);
connection_mark_for_close(conn);
}
@@ -5093,15 +5158,29 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(!SOCKET_OK(conn->s));

if (conn->outbuf_flushlen > 0) {
/* With optimistic data, we may have queued data in
* EXIT_CONN_STATE_RESOLVING while the conn is not yet marked to writing.
* */
tor_assert((conn->type == CONN_TYPE_EXIT &&
conn->state == EXIT_CONN_STATE_RESOLVING) ||
connection_is_writing(conn) ||
conn->write_blocked_on_bw ||
(CONN_IS_EDGE(conn) &&
TO_EDGE_CONN(conn)->edge_blocked_on_circ));
if (CONN_IS_EDGE(conn)) {
if (conn->type == CONN_TYPE_EXIT) {
/* With optimistic data, we may have queued data in
* EXIT_CONN_STATE_RESOLVING while the conn is not yet marked to
* writing.
* */
if (conn->state != EXIT_CONN_STATE_RESOLVING) {
tor_assertf(connection_is_writing(conn) || conn->write_blocked_on_bw,
"Exit connection %llu is neither resolving, "
"nor writing out it's nonempty outbuf",
conn->global_identifier);
}
} else if (TO_EDGE_CONN(conn)->edge_blocked_on_circ == 0) {
tor_assertf(connection_is_writing(conn) || conn->write_blocked_on_bw,
"Edge connection %llu is neither blocked nor "
"writing out it's nonempty outbuf",
conn->global_identifier);
}
} else {
tor_assertf(connection_is_writing(conn) || conn->write_blocked_on_bw,
"Connection %llu is not writing out it's nonempty outbuf",
conn->global_identifier);
}
}

if (conn->hold_open_until_flushed)
@@ -40,6 +40,10 @@ void connection_mark_for_close_(connection_t *conn,
MOCK_DECL(void, connection_mark_for_close_internal_,
(connection_t *conn, int line, const char *file));

void connection_remove_child(connection_t *parent, connection_t *child);
void connection_add_child(connection_t *parent, connection_t *child);
void close_child_connections(connection_t *conn);

#define connection_mark_for_close(c) \
connection_mark_for_close_((c), __LINE__, SHORT_FILE__)
#define connection_mark_for_close_internal(c) \
@@ -317,7 +317,6 @@ typedef enum {
* start accepting OR connections. */
#define EXT_OR_CONN_STATE_FLUSHING 5
#define EXT_OR_CONN_STATE_MAX_ 5

#define EXIT_CONN_STATE_MIN_ 1
/** State for an exit connection: waiting for response from DNS farm. */
#define EXIT_CONN_STATE_RESOLVING 1
@@ -1402,6 +1401,10 @@ typedef struct connection_t {
/** Bytes written since last call to control_event_conn_bandwidth_used().
* Only used if we're configured to emit CONN_BW events. */
uint32_t n_written_conn_bw;

/** There could be parent-child relationship between connections. */
smartlist_t *children;
struct connection_t *parent;
} connection_t;

/** Subtype of connection_t; used for a listener socket. */

No commit comments for this range