1 /* Copyright (c) 2003-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2013, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
8 * \brief Implements a farm of 'CPU worker' processes to perform
9 * CPU-intensive tasks in another thread or process, to not
10 * interrupt the main thread.
12 * Right now, we only use this for processing onionskins.
17 #include "channeltls.h"
18 #include "circuitbuild.h"
19 #include "circuitlist.h"
21 #include "connection.h"
22 #include "connection_or.h"
23 #include "cpuworker.h"
29 /** The maximum number of cpuworker processes we will keep around. */
30 #define MAX_CPUWORKERS 16
31 /** The minimum number of cpuworker processes we will keep around. */
32 #define MIN_CPUWORKERS 1
34 /** The tag specifies which circuit this onionskin was from. */
37 /** How many cpuworkers we have running right now. */
38 static int num_cpuworkers
=0;
39 /** How many of the running cpuworkers have an assigned task right now. */
40 static int num_cpuworkers_busy
=0;
41 /** We need to spawn new cpuworkers whenever we rotate the onion keys
42 * on platforms where execution contexts==processes. This variable stores
43 * the last time we got a key rotation event. */
44 static time_t last_rotation_time
=0;
46 static void cpuworker_main(void *data
) ATTR_NORETURN
;
47 static int spawn_cpuworker(void);
48 static void spawn_enough_cpuworkers(void);
49 static void process_pending_task(connection_t
*cpuworker
);
51 /** Initialize the cpuworker subsystem.
59 /** Called when we're done sending a request to a cpuworker. */
61 connection_cpu_finished_flushing(connection_t
*conn
)
64 tor_assert(conn
->type
== CONN_TYPE_CPUWORKER
);
68 /** Pack global_id and circ_id; set *tag to the result. (See note on
69 * cpuworker_main for wire format.) */
71 tag_pack(uint8_t *tag
, uint64_t chan_id
, circid_t circ_id
)
73 /*XXXX RETHINK THIS WHOLE MESS !!!! !NM NM NM NM*/
74 /*XXXX DOUBLEPLUSTHIS!!!! AS AS AS AS*/
75 set_uint64(tag
, chan_id
);
76 set_uint32(tag
+8, circ_id
);
79 /** Unpack <b>tag</b> into addr, port, and circ_id.
82 tag_unpack(const uint8_t *tag
, uint64_t *chan_id
, circid_t
*circ_id
)
84 *chan_id
= get_uint64(tag
);
85 *circ_id
= get_uint32(tag
+8);
88 /** Magic numbers to make sure our cpuworker_requests don't grow any
89 * mis-framing bugs. */
90 #define CPUWORKER_REQUEST_MAGIC 0xda4afeed
91 #define CPUWORKER_REPLY_MAGIC 0x5eedf00d
93 /** A request sent to a cpuworker. */
94 typedef struct cpuworker_request_t
{
95 /** Magic number; must be CPUWORKER_REQUEST_MAGIC. */
97 /** Opaque tag to identify the job */
99 /** Task code. Must be one of CPUWORKER_TASK_* */
102 /** Flag: Are we timing this request? */
104 /** If we're timing this request, when was it sent to the cpuworker? */
105 struct timeval started_at
;
107 /** A create cell for the cpuworker to process. */
108 create_cell_t create_cell
;
110 /* Turn the above into a tagged union if needed. */
111 } cpuworker_request_t
;
113 /** A reply sent by a cpuworker. */
114 typedef struct cpuworker_reply_t
{
115 /** Magic number; must be CPUWORKER_REPLY_MAGIC. */
117 /** Opaque tag to identify the job; matches the request's tag.*/
118 uint8_t tag
[TAG_LEN
];
119 /** True iff we got a successful request. */
122 /** Are we timing this request? */
123 unsigned int timed
: 1;
124 /** What handshake type was the request? (Used for timing) */
125 uint16_t handshake_type
;
126 /** When did we send the request to the cpuworker? */
127 struct timeval started_at
;
128 /** Once the cpuworker received the request, how many microseconds did it
129 * take? (This shouldn't overflow; 4 billion micoseconds is over an hour,
130 * and we'll never have an onion handshake that takes so long.) */
133 /** Output of processing a create cell
137 /** The created cell to send back. */
138 created_cell_t created_cell
;
139 /** The keys to use on this circuit. */
140 uint8_t keys
[CPATH_KEY_MATERIAL_LEN
];
141 /** Input to use for authenticating introduce1 cells. */
142 uint8_t rend_auth_material
[DIGEST_LEN
];
145 /** Called when the onion key has changed and we need to spawn new
146 * cpuworkers. Close all currently idle cpuworkers, and mark the last
147 * rotation time as now.
150 cpuworkers_rotate(void)
152 connection_t
*cpuworker
;
153 while ((cpuworker
= connection_get_by_type_state(CONN_TYPE_CPUWORKER
,
154 CPUWORKER_STATE_IDLE
))) {
155 connection_mark_for_close(cpuworker
);
158 last_rotation_time
= time(NULL
);
159 if (server_mode(get_options()))
160 spawn_enough_cpuworkers();
163 /** If the cpuworker closes the connection,
164 * mark it as closed and spawn a new one as needed. */
166 connection_cpu_reached_eof(connection_t
*conn
)
168 log_warn(LD_GENERAL
,"Read eof. CPU worker died unexpectedly.");
169 if (conn
->state
!= CPUWORKER_STATE_IDLE
) {
170 /* the circ associated with this cpuworker will have to wait until
171 * it gets culled in run_connection_housekeeping(), since we have
172 * no way to find out which circ it was. */
173 log_warn(LD_GENERAL
,"...and it left a circuit queued; abandoning circ.");
174 num_cpuworkers_busy
--;
177 spawn_enough_cpuworkers(); /* try to regrow. hope we don't end up
179 connection_mark_for_close(conn
);
183 /** Indexed by handshake type: how many onionskins have we processed and
184 * counted of that type? */
185 static uint64_t onionskins_n_processed
[MAX_ONION_HANDSHAKE_TYPE
+1];
186 /** Indexed by handshake type, corresponding to the onionskins counted in
187 * onionskins_n_processed: how many microseconds have we spent in cpuworkers
188 * processing that kind of onionskin? */
189 static uint64_t onionskins_usec_internal
[MAX_ONION_HANDSHAKE_TYPE
+1];
190 /** Indexed by handshake type, corresponding to onionskins counted in
191 * onionskins_n_processed: how many microseconds have we spent waiting for
192 * cpuworkers to give us answers for that kind of onionskin?
194 static uint64_t onionskins_usec_roundtrip
[MAX_ONION_HANDSHAKE_TYPE
+1];
196 /** If any onionskin takes longer than this, we clip them to this
197 * time. (microseconds) */
198 #define MAX_BELIEVABLE_ONIONSKIN_DELAY (2*1000*1000)
200 static tor_weak_rng_t request_sample_rng
= TOR_WEAK_RNG_INIT
;
202 /** Return true iff we'd like to measure a handshake of type
203 * <b>onionskin_type</b>. Call only from the main thread. */
205 should_time_request(uint16_t onionskin_type
)
207 /* If we've never heard of this type, we shouldn't even be here. */
208 if (onionskin_type
> MAX_ONION_HANDSHAKE_TYPE
)
210 /* Measure the first N handshakes of each type, to ensure we have a
212 if (onionskins_n_processed
[onionskin_type
] < 4096)
214 /** Otherwise, measure with P=1/128. We avoid doing this for every
215 * handshake, since the measurement itself can take a little time. */
216 return tor_weak_random_one_in_n(&request_sample_rng
, 128);
219 /** Return an estimate of how many microseconds we will need for a single
220 * cpuworker to to process <b>n_requests</b> onionskins of type
221 * <b>onionskin_type</b>. */
223 estimated_usec_for_onionskins(uint32_t n_requests
, uint16_t onionskin_type
)
225 if (onionskin_type
> MAX_ONION_HANDSHAKE_TYPE
) /* should be impossible */
226 return 1000 * (uint64_t)n_requests
;
227 if (PREDICT_UNLIKELY(onionskins_n_processed
[onionskin_type
] < 100)) {
228 /* Until we have 100 data points, just asssume everything takes 1 msec. */
229 return 1000 * (uint64_t)n_requests
;
231 /* This can't overflow: we'll never have more than 500000 onionskins
232 * measured in onionskin_usec_internal, and they won't take anything near
233 * 1 sec each, and we won't have anything like 1 million queued
234 * onionskins. But that's 5e5 * 1e6 * 1e6, which is still less than
236 return (onionskins_usec_internal
[onionskin_type
] * n_requests
) /
237 onionskins_n_processed
[onionskin_type
];
241 /** Compute the absolute and relative overhead of using the cpuworker
242 * framework for onionskins of type <b>onionskin_type</b>.*/
244 get_overhead_for_onionskins(uint32_t *usec_out
, double *frac_out
,
245 uint16_t onionskin_type
)
252 if (onionskin_type
> MAX_ONION_HANDSHAKE_TYPE
) /* should be impossible */
254 if (onionskins_n_processed
[onionskin_type
] == 0 ||
255 onionskins_usec_internal
[onionskin_type
] == 0 ||
256 onionskins_usec_roundtrip
[onionskin_type
] == 0)
259 overhead
= onionskins_usec_roundtrip
[onionskin_type
] -
260 onionskins_usec_internal
[onionskin_type
];
262 *usec_out
= (uint32_t)(overhead
/ onionskins_n_processed
[onionskin_type
]);
263 *frac_out
= U64_TO_DBL(overhead
) / onionskins_usec_internal
[onionskin_type
];
268 /** If we've measured overhead for onionskins of type <b>onionskin_type</b>,
271 cpuworker_log_onionskin_overhead(int severity
, int onionskin_type
,
272 const char *onionskin_type_name
)
275 double relative_overhead
;
278 r
= get_overhead_for_onionskins(&overhead
, &relative_overhead
,
280 if (!overhead
|| r
<0)
283 log_fn(severity
, LD_OR
,
284 "%s onionskins have averaged %u usec overhead (%.2f%%) in "
286 onionskin_type_name
, (unsigned)overhead
, relative_overhead
*100);
289 /** Called when we get data from a cpuworker. If the answer is not complete,
290 * wait for a complete answer. If the answer is complete,
291 * process it as appropriate.
294 connection_cpu_process_inbuf(connection_t
*conn
)
298 channel_t
*p_chan
= NULL
;
302 tor_assert(conn
->type
== CONN_TYPE_CPUWORKER
);
304 if (!connection_get_inbuf_len(conn
))
307 if (conn
->state
== CPUWORKER_STATE_BUSY_ONION
) {
308 cpuworker_reply_t rpl
;
309 if (connection_get_inbuf_len(conn
) < sizeof(cpuworker_reply_t
))
310 return 0; /* not yet */
311 tor_assert(connection_get_inbuf_len(conn
) == sizeof(cpuworker_reply_t
));
313 connection_fetch_from_buf((void*)&rpl
,sizeof(cpuworker_reply_t
),conn
);
315 tor_assert(rpl
.magic
== CPUWORKER_REPLY_MAGIC
);
317 if (rpl
.timed
&& rpl
.success
&&
318 rpl
.handshake_type
<= MAX_ONION_HANDSHAKE_TYPE
) {
319 /* Time how long this request took. The handshake_type check should be
320 needless, but let's leave it in to be safe. */
321 struct timeval tv_end
, tv_diff
;
322 int64_t usec_roundtrip
;
323 tor_gettimeofday(&tv_end
);
324 timersub(&tv_end
, &rpl
.started_at
, &tv_diff
);
325 usec_roundtrip
= ((int64_t)tv_diff
.tv_sec
)*1000000 + tv_diff
.tv_usec
;
326 if (usec_roundtrip
>= 0 &&
327 usec_roundtrip
< MAX_BELIEVABLE_ONIONSKIN_DELAY
) {
328 ++onionskins_n_processed
[rpl
.handshake_type
];
329 onionskins_usec_internal
[rpl
.handshake_type
] += rpl
.n_usec
;
330 onionskins_usec_roundtrip
[rpl
.handshake_type
] += usec_roundtrip
;
331 if (onionskins_n_processed
[rpl
.handshake_type
] >= 500000) {
332 /* Scale down every 500000 handshakes. On a busy server, that's
333 * less impressive than it sounds. */
334 onionskins_n_processed
[rpl
.handshake_type
] /= 2;
335 onionskins_usec_internal
[rpl
.handshake_type
] /= 2;
336 onionskins_usec_roundtrip
[rpl
.handshake_type
] /= 2;
340 /* parse out the circ it was talking about */
341 tag_unpack(rpl
.tag
, &chan_id
, &circ_id
);
344 "Unpacking cpuworker reply, chan_id is " U64_FORMAT
346 U64_PRINTF_ARG(chan_id
), (unsigned)circ_id
);
347 p_chan
= channel_find_by_global_id(chan_id
);
350 circ
= circuit_get_by_circid_channel(circ_id
, p_chan
);
352 if (rpl
.success
== 0) {
354 "decoding onionskin failed. "
355 "(Old key or bad software.) Closing.");
357 circuit_mark_for_close(circ
, END_CIRC_REASON_TORPROTOCOL
);
358 goto done_processing
;
361 /* This happens because somebody sends us a destroy cell and the
362 * circuit goes away, while the cpuworker is working. This is also
363 * why our tag doesn't include a pointer to the circ, because we'd
364 * never know if it's still valid.
366 log_debug(LD_OR
,"processed onion for a circ that's gone. Dropping.");
367 goto done_processing
;
369 tor_assert(! CIRCUIT_IS_ORIGIN(circ
));
370 if (onionskin_answer(TO_OR_CIRCUIT(circ
),
372 (const char*)rpl
.keys
,
373 rpl
.rend_auth_material
) < 0) {
374 log_warn(LD_OR
,"onionskin_answer failed. Closing.");
375 circuit_mark_for_close(circ
, END_CIRC_REASON_INTERNAL
);
376 goto done_processing
;
378 log_debug(LD_OR
,"onionskin_answer succeeded. Yay.");
380 tor_assert(0); /* don't ask me to do handshakes yet */
384 conn
->state
= CPUWORKER_STATE_IDLE
;
385 num_cpuworkers_busy
--;
386 if (conn
->timestamp_created
< last_rotation_time
) {
387 connection_mark_for_close(conn
);
389 spawn_enough_cpuworkers();
391 process_pending_task(conn
);
396 /** Implement a cpuworker. 'data' is an fdarray as returned by socketpair.
397 * Read and writes from fdarray[1]. Reads requests, writes answers.
400 * cpuworker_request_t.
405 cpuworker_main(void *data
)
407 /* For talking to the parent thread/process */
408 tor_socket_t
*fdarray
= data
;
411 /* variables for onion processing */
412 server_onion_keys_t onion_keys
;
413 cpuworker_request_t req
;
414 cpuworker_reply_t rpl
;
416 fd
= fdarray
[1]; /* this side is ours */
417 #ifndef TOR_IS_MULTITHREADED
418 tor_close_socket(fdarray
[0]); /* this is the side of the socketpair the
420 tor_free_all(1); /* so the child doesn't hold the parent's fd's open */
421 handle_signals(0); /* ignore interrupts from the keyboard, etc */
425 setup_server_onion_keys(&onion_keys
);
428 if (read_all(fd
, (void *)&req
, sizeof(req
), 1) != sizeof(req
)) {
429 log_info(LD_OR
, "read request failed. Exiting.");
432 tor_assert(req
.magic
== CPUWORKER_REQUEST_MAGIC
);
434 memset(&rpl
, 0, sizeof(rpl
));
436 if (req
.task
== CPUWORKER_TASK_ONION
) {
437 const create_cell_t
*cc
= &req
.create_cell
;
438 created_cell_t
*cell_out
= &rpl
.created_cell
;
439 struct timeval tv_start
= {0,0}, tv_end
;
441 rpl
.timed
= req
.timed
;
442 rpl
.started_at
= req
.started_at
;
443 rpl
.handshake_type
= cc
->handshake_type
;
445 tor_gettimeofday(&tv_start
);
446 n
= onion_skin_server_handshake(cc
->handshake_type
,
447 cc
->onionskin
, cc
->handshake_len
,
450 rpl
.keys
, CPATH_KEY_MATERIAL_LEN
,
451 rpl
.rend_auth_material
);
454 log_debug(LD_OR
,"onion_skin_server_handshake failed.");
455 memset(&rpl
, 0, sizeof(rpl
));
456 memcpy(rpl
.tag
, req
.tag
, TAG_LEN
);
460 log_debug(LD_OR
,"onion_skin_server_handshake succeeded.");
461 memcpy(rpl
.tag
, req
.tag
, TAG_LEN
);
462 cell_out
->handshake_len
= n
;
463 switch (cc
->cell_type
) {
465 cell_out
->cell_type
= CELL_CREATED
; break;
467 cell_out
->cell_type
= CELL_CREATED2
; break;
468 case CELL_CREATE_FAST
:
469 cell_out
->cell_type
= CELL_CREATED_FAST
; break;
476 rpl
.magic
= CPUWORKER_REPLY_MAGIC
;
478 struct timeval tv_diff
;
480 tor_gettimeofday(&tv_end
);
481 timersub(&tv_end
, &tv_start
, &tv_diff
);
482 usec
= ((int64_t)tv_diff
.tv_sec
)*1000000 + tv_diff
.tv_usec
;
483 if (usec
< 0 || usec
> MAX_BELIEVABLE_ONIONSKIN_DELAY
)
484 rpl
.n_usec
= MAX_BELIEVABLE_ONIONSKIN_DELAY
;
486 rpl
.n_usec
= (uint32_t) usec
;
488 if (write_all(fd
, (void*)&rpl
, sizeof(rpl
), 1) != sizeof(rpl
)) {
489 log_err(LD_BUG
,"writing response buf failed. Exiting.");
492 log_debug(LD_OR
,"finished writing response.");
493 } else if (req
.task
== CPUWORKER_TASK_SHUTDOWN
) {
494 log_info(LD_OR
,"Clean shutdown: exiting");
497 memwipe(&req
, 0, sizeof(req
));
498 memwipe(&rpl
, 0, sizeof(req
));
501 memwipe(&req
, 0, sizeof(req
));
502 memwipe(&rpl
, 0, sizeof(req
));
503 release_server_onion_keys(&onion_keys
);
504 tor_close_socket(fd
);
505 crypto_thread_cleanup();
509 /** Launch a new cpuworker. Return 0 if we're happy, -1 if we failed.
512 spawn_cpuworker(void)
514 tor_socket_t
*fdarray
;
519 fdarray
= tor_malloc(sizeof(tor_socket_t
)*2);
520 if ((err
= tor_socketpair(AF_UNIX
, SOCK_STREAM
, 0, fdarray
)) < 0) {
521 log_warn(LD_NET
, "Couldn't construct socketpair for cpuworker: %s",
522 tor_socket_strerror(-err
));
527 tor_assert(SOCKET_OK(fdarray
[0]));
528 tor_assert(SOCKET_OK(fdarray
[1]));
531 if (spawn_func(cpuworker_main
, (void*)fdarray
) < 0) {
532 tor_close_socket(fdarray
[0]);
533 tor_close_socket(fdarray
[1]);
537 log_debug(LD_OR
,"just spawned a cpu worker.");
538 #ifndef TOR_IS_MULTITHREADED
539 tor_close_socket(fdarray
[1]); /* don't need the worker's side of the pipe */
543 conn
= connection_new(CONN_TYPE_CPUWORKER
, AF_UNIX
);
545 /* set up conn so it's got all the data we need to remember */
547 conn
->address
= tor_strdup("localhost");
548 tor_addr_make_unspec(&conn
->addr
);
550 if (set_socket_nonblocking(fd
) == -1) {
551 connection_free(conn
); /* this closes fd */
555 if (connection_add(conn
) < 0) { /* no space, forget it */
556 log_warn(LD_NET
,"connection_add for cpuworker failed. Giving up.");
557 connection_free(conn
); /* this closes fd */
561 conn
->state
= CPUWORKER_STATE_IDLE
;
562 connection_start_reading(conn
);
564 return 0; /* success */
567 /** If we have too few or too many active cpuworkers, try to spawn new ones
571 spawn_enough_cpuworkers(void)
573 int num_cpuworkers_needed
= get_num_cpus(get_options());
576 if (num_cpuworkers_needed
< MIN_CPUWORKERS
)
577 num_cpuworkers_needed
= MIN_CPUWORKERS
;
578 if (num_cpuworkers_needed
> MAX_CPUWORKERS
)
579 num_cpuworkers_needed
= MAX_CPUWORKERS
;
581 while (num_cpuworkers
< num_cpuworkers_needed
) {
582 if (spawn_cpuworker() < 0) {
583 log_warn(LD_GENERAL
,"Cpuworker spawn failed. Will try again later.");
591 crypto_seed_weak_rng(&request_sample_rng
);
594 /** Take a pending task from the queue and assign it to 'cpuworker'. */
596 process_pending_task(connection_t
*cpuworker
)
599 create_cell_t
*onionskin
= NULL
;
601 tor_assert(cpuworker
);
603 /* for now only process onion tasks */
605 circ
= onion_next_task(&onionskin
);
608 if (assign_onionskin_to_cpuworker(cpuworker
, circ
, onionskin
))
609 log_warn(LD_OR
,"assign_to_cpuworker failed. Ignoring.");
612 /** How long should we let a cpuworker stay busy before we give
613 * up on it and decide that we have a bug or infinite loop?
614 * This value is high because some servers with low memory/cpu
615 * sometimes spend an hour or more swapping, and Tor starves. */
616 #define CPUWORKER_BUSY_TIMEOUT (60*60*12)
618 /** We have a bug that I can't find. Sometimes, very rarely, cpuworkers get
619 * stuck in the 'busy' state, even though the cpuworker process thinks of
620 * itself as idle. I don't know why. But here's a workaround to kill any
621 * cpuworker that's been busy for more than CPUWORKER_BUSY_TIMEOUT.
624 cull_wedged_cpuworkers(void)
626 time_t now
= time(NULL
);
627 smartlist_t
*conns
= get_connection_array();
628 SMARTLIST_FOREACH_BEGIN(conns
, connection_t
*, conn
) {
629 if (!conn
->marked_for_close
&&
630 conn
->type
== CONN_TYPE_CPUWORKER
&&
631 conn
->state
== CPUWORKER_STATE_BUSY_ONION
&&
632 conn
->timestamp_lastwritten
+ CPUWORKER_BUSY_TIMEOUT
< now
) {
634 "closing wedged cpuworker. Can somebody find the bug?");
635 num_cpuworkers_busy
--;
637 connection_mark_for_close(conn
);
639 } SMARTLIST_FOREACH_END(conn
);
642 /** Try to tell a cpuworker to perform the public key operations necessary to
643 * respond to <b>onionskin</b> for the circuit <b>circ</b>.
645 * If <b>cpuworker</b> is defined, assert that he's idle, and use him. Else,
646 * look for an idle cpuworker and use him. If none idle, queue task onto the
647 * pending onion list and return. Return 0 if we successfully assign the
648 * task, or -1 on failure.
651 assign_onionskin_to_cpuworker(connection_t
*cpuworker
,
653 create_cell_t
*onionskin
)
655 cpuworker_request_t req
;
656 time_t now
= approx_time();
657 static time_t last_culled_cpuworkers
= 0;
660 /* Checking for wedged cpuworkers requires a linear search over all
661 * connections, so let's do it only once a minute.
663 #define CULL_CPUWORKERS_INTERVAL 60
665 if (last_culled_cpuworkers
+ CULL_CPUWORKERS_INTERVAL
<= now
) {
666 cull_wedged_cpuworkers();
667 spawn_enough_cpuworkers();
668 last_culled_cpuworkers
= now
;
672 if (num_cpuworkers_busy
== num_cpuworkers
) {
673 log_debug(LD_OR
,"No idle cpuworkers. Queuing.");
674 if (onion_pending_add(circ
, onionskin
) < 0) {
682 cpuworker
= connection_get_by_type_state(CONN_TYPE_CPUWORKER
,
683 CPUWORKER_STATE_IDLE
);
685 tor_assert(cpuworker
);
688 log_info(LD_OR
,"circ->p_chan gone. Failing circ.");
693 if (connection_or_digest_is_known_relay(circ
->p_chan
->identity_digest
))
694 rep_hist_note_circuit_handshake_assigned(onionskin
->handshake_type
);
696 should_time
= should_time_request(onionskin
->handshake_type
);
697 memset(&req
, 0, sizeof(req
));
698 req
.magic
= CPUWORKER_REQUEST_MAGIC
;
699 tag_pack(req
.tag
, circ
->p_chan
->global_identifier
,
701 req
.timed
= should_time
;
703 cpuworker
->state
= CPUWORKER_STATE_BUSY_ONION
;
704 /* touch the lastwritten timestamp, since that's how we check to
705 * see how long it's been since we asked the question, and sometimes
706 * we check before the first call to connection_handle_write(). */
707 cpuworker
->timestamp_lastwritten
= now
;
708 num_cpuworkers_busy
++;
710 req
.task
= CPUWORKER_TASK_ONION
;
711 memcpy(&req
.create_cell
, onionskin
, sizeof(create_cell_t
));
716 tor_gettimeofday(&req
.started_at
);
718 connection_write_to_buf((void*)&req
, sizeof(req
), cpuworker
);
719 memwipe(&req
, 0, sizeof(req
));