mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Avoid chan/circ linear lookups for requests
The solution I took is to not free a circuit with a pending uncancellable work item, but rather to set its magic number to a sentinel value. When we get a work item, we check whether the circuit has that magic sentinel, and if so, we free it rather than processing the reply.
This commit is contained in:
parent
6c9c54e7fa
commit
fb5ebfb507
@ -745,6 +745,7 @@ circuit_free(circuit_t *circ)
|
|||||||
{
|
{
|
||||||
void *mem;
|
void *mem;
|
||||||
size_t memlen;
|
size_t memlen;
|
||||||
|
int should_free = 1;
|
||||||
if (!circ)
|
if (!circ)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -784,6 +785,8 @@ circuit_free(circuit_t *circ)
|
|||||||
memlen = sizeof(or_circuit_t);
|
memlen = sizeof(or_circuit_t);
|
||||||
tor_assert(circ->magic == OR_CIRCUIT_MAGIC);
|
tor_assert(circ->magic == OR_CIRCUIT_MAGIC);
|
||||||
|
|
||||||
|
should_free = (ocirc->workqueue_entry == NULL);
|
||||||
|
|
||||||
crypto_cipher_free(ocirc->p_crypto);
|
crypto_cipher_free(ocirc->p_crypto);
|
||||||
crypto_digest_free(ocirc->p_digest);
|
crypto_digest_free(ocirc->p_digest);
|
||||||
crypto_cipher_free(ocirc->n_crypto);
|
crypto_cipher_free(ocirc->n_crypto);
|
||||||
@ -826,8 +829,18 @@ circuit_free(circuit_t *circ)
|
|||||||
* "active" checks will be violated. */
|
* "active" checks will be violated. */
|
||||||
cell_queue_clear(&circ->n_chan_cells);
|
cell_queue_clear(&circ->n_chan_cells);
|
||||||
|
|
||||||
|
if (should_free) {
|
||||||
memwipe(mem, 0xAA, memlen); /* poison memory */
|
memwipe(mem, 0xAA, memlen); /* poison memory */
|
||||||
tor_free(mem);
|
tor_free(mem);
|
||||||
|
} else {
|
||||||
|
/* If we made it here, this is an or_circuit_t that still has a pending
|
||||||
|
* cpuworker request which we weren't able to cancel. Instead, set up
|
||||||
|
* the magic value so that when the reply comes back, we'll know to discard
|
||||||
|
* the reply and free this structure.
|
||||||
|
*/
|
||||||
|
memwipe(mem, 0xAA, memlen);
|
||||||
|
circ->magic = DEAD_CIRCUIT_MAGIC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Deallocate the linked list circ-><b>cpath</b>, and remove the cpath from
|
/** Deallocate the linked list circ-><b>cpath</b>, and remove the cpath from
|
||||||
|
@ -152,8 +152,7 @@ typedef struct cpuworker_reply_t {
|
|||||||
} cpuworker_reply_t;
|
} cpuworker_reply_t;
|
||||||
|
|
||||||
typedef struct cpuworker_job_u {
|
typedef struct cpuworker_job_u {
|
||||||
uint64_t chan_id;
|
or_circuit_t *circ;
|
||||||
uint32_t circ_id;
|
|
||||||
union {
|
union {
|
||||||
cpuworker_request_t request;
|
cpuworker_request_t request;
|
||||||
cpuworker_reply_t reply;
|
cpuworker_reply_t reply;
|
||||||
@ -297,16 +296,13 @@ cpuworker_log_onionskin_overhead(int severity, int onionskin_type,
|
|||||||
onionskin_type_name, (unsigned)overhead, relative_overhead*100);
|
onionskin_type_name, (unsigned)overhead, relative_overhead*100);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
/** Handle a reply from the worker threads. */
|
||||||
static void
|
static void
|
||||||
cpuworker_onion_handshake_replyfn(void *work_)
|
cpuworker_onion_handshake_replyfn(void *work_)
|
||||||
{
|
{
|
||||||
cpuworker_job_t *job = work_;
|
cpuworker_job_t *job = work_;
|
||||||
cpuworker_reply_t rpl;
|
cpuworker_reply_t rpl;
|
||||||
uint64_t chan_id;
|
or_circuit_t *circ = NULL;
|
||||||
circid_t circ_id;
|
|
||||||
channel_t *p_chan = NULL;
|
|
||||||
circuit_t *circ = NULL;
|
|
||||||
|
|
||||||
--total_pending_tasks;
|
--total_pending_tasks;
|
||||||
|
|
||||||
@ -338,46 +334,40 @@ cpuworker_onion_handshake_replyfn(void *work_)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Find the circ it was talking about */
|
|
||||||
chan_id = job->chan_id;
|
|
||||||
circ_id = job->circ_id;
|
|
||||||
|
|
||||||
p_chan = channel_find_by_global_id(chan_id);
|
circ = job->circ;
|
||||||
|
|
||||||
if (p_chan)
|
|
||||||
circ = circuit_get_by_circid_channel(circ_id, p_chan);
|
|
||||||
|
|
||||||
log_debug(LD_OR,
|
log_debug(LD_OR,
|
||||||
"Unpacking cpuworker reply %p, chan_id is " U64_FORMAT
|
"Unpacking cpuworker reply %p, circ=%p, success=%d",
|
||||||
", circ_id is %u, p_chan=%p, circ=%p, success=%d",
|
job, circ, rpl.success);
|
||||||
job, U64_PRINTF_ARG(chan_id), (unsigned)circ_id,
|
|
||||||
p_chan, circ, rpl.success);
|
if (circ->base_.magic == DEAD_CIRCUIT_MAGIC) {
|
||||||
|
/* The circuit was supposed to get freed while the reply was
|
||||||
|
* pending. Instead, it got left for us to free so that we wouldn't freak
|
||||||
|
* out when the job->circ field wound up pointing to nothing. */
|
||||||
|
log_debug(LD_OR, "Circuit died while reply was pending. Freeing memory.");
|
||||||
|
circ->base_.magic = 0;
|
||||||
|
tor_free(circ);
|
||||||
|
goto done_processing;
|
||||||
|
}
|
||||||
|
|
||||||
|
circ->workqueue_entry = NULL;
|
||||||
|
|
||||||
if (rpl.success == 0) {
|
if (rpl.success == 0) {
|
||||||
log_debug(LD_OR,
|
log_debug(LD_OR,
|
||||||
"decoding onionskin failed. "
|
"decoding onionskin failed. "
|
||||||
"(Old key or bad software.) Closing.");
|
"(Old key or bad software.) Closing.");
|
||||||
if (circ)
|
if (circ)
|
||||||
circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
|
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
|
||||||
goto done_processing;
|
goto done_processing;
|
||||||
}
|
}
|
||||||
if (!circ) {
|
|
||||||
/* This happens because somebody sends us a destroy cell and the
|
if (onionskin_answer(circ,
|
||||||
* circuit goes away, while the cpuworker is working. This is also
|
|
||||||
* why our tag doesn't include a pointer to the circ, because we'd
|
|
||||||
* never know if it's still valid.
|
|
||||||
*/
|
|
||||||
log_debug(LD_OR,"processed onion for a circ that's gone. Dropping.");
|
|
||||||
goto done_processing;
|
|
||||||
}
|
|
||||||
tor_assert(! CIRCUIT_IS_ORIGIN(circ));
|
|
||||||
TO_OR_CIRCUIT(circ)->workqueue_entry = NULL;
|
|
||||||
if (onionskin_answer(TO_OR_CIRCUIT(circ),
|
|
||||||
&rpl.created_cell,
|
&rpl.created_cell,
|
||||||
(const char*)rpl.keys,
|
(const char*)rpl.keys,
|
||||||
rpl.rend_auth_material) < 0) {
|
rpl.rend_auth_material) < 0) {
|
||||||
log_warn(LD_OR,"onionskin_answer failed. Closing.");
|
log_warn(LD_OR,"onionskin_answer failed. Closing.");
|
||||||
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
|
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
|
||||||
goto done_processing;
|
goto done_processing;
|
||||||
}
|
}
|
||||||
log_debug(LD_OR,"onionskin_answer succeeded. Yay.");
|
log_debug(LD_OR,"onionskin_answer succeeded. Yay.");
|
||||||
@ -527,8 +517,7 @@ assign_onionskin_to_cpuworker(or_circuit_t *circ,
|
|||||||
tor_gettimeofday(&req.started_at);
|
tor_gettimeofday(&req.started_at);
|
||||||
|
|
||||||
job = tor_malloc_zero(sizeof(cpuworker_job_t));
|
job = tor_malloc_zero(sizeof(cpuworker_job_t));
|
||||||
job->chan_id = circ->p_chan->global_identifier;
|
job->circ = circ;
|
||||||
job->circ_id = circ->p_circ_id;
|
|
||||||
memcpy(&job->u.request, &req, sizeof(req));
|
memcpy(&job->u.request, &req, sizeof(req));
|
||||||
memwipe(&req, 0, sizeof(req));
|
memwipe(&req, 0, sizeof(req));
|
||||||
|
|
||||||
@ -542,8 +531,9 @@ assign_onionskin_to_cpuworker(or_circuit_t *circ,
|
|||||||
tor_free(job);
|
tor_free(job);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
log_debug(LD_OR, "Queued task %p (qe=%p, chanid="U64_FORMAT", circid=%u)",
|
|
||||||
job, queue_entry, U64_PRINTF_ARG(job->chan_id), job->circ_id);
|
log_debug(LD_OR, "Queued task %p (qe=%p, circ=%p)",
|
||||||
|
job, queue_entry, job->circ);
|
||||||
|
|
||||||
circ->workqueue_entry = queue_entry;
|
circ->workqueue_entry = queue_entry;
|
||||||
|
|
||||||
|
@ -2725,8 +2725,14 @@ typedef struct {
|
|||||||
time_t expiry_time;
|
time_t expiry_time;
|
||||||
} cpath_build_state_t;
|
} cpath_build_state_t;
|
||||||
|
|
||||||
|
/** "magic" value for an origin_circuit_t */
|
||||||
#define ORIGIN_CIRCUIT_MAGIC 0x35315243u
|
#define ORIGIN_CIRCUIT_MAGIC 0x35315243u
|
||||||
|
/** "magic" value for an or_circuit_t */
|
||||||
#define OR_CIRCUIT_MAGIC 0x98ABC04Fu
|
#define OR_CIRCUIT_MAGIC 0x98ABC04Fu
|
||||||
|
/** "magic" value for a circuit that would have been freed by circuit_free,
|
||||||
|
* but which we're keeping around until a cpuworker reply arrives. See
|
||||||
|
* circuit_free() for more documentation. */
|
||||||
|
#define DEAD_CIRCUIT_MAGIC 0xdeadc14c
|
||||||
|
|
||||||
struct create_cell_t;
|
struct create_cell_t;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user