aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>2018-01-02 16:48:03 +0100
committerSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>2018-01-02 16:48:03 +0100
commit7c1f035ed971e12882cd7a65c7d36883842945b1 (patch)
tree3828089ef8124270b976ac94902ba27210d275a3 /src/util
parent92d8c8a77e242a61927acc0e22fcecea479e6c43 (diff)
parent61f532f18450e0d7c72f0c17f4a20b5854cf53bf (diff)
downloadgnunet-7c1f035ed971e12882cd7a65c7d36883842945b1.tar.gz
gnunet-7c1f035ed971e12882cd7a65c7d36883842945b1.zip
-merge
Diffstat (limited to 'src/util')
-rw-r--r--src/util/client.c41
-rw-r--r--src/util/mq.c22
-rw-r--r--src/util/mst.c27
-rw-r--r--src/util/network.c6
-rw-r--r--src/util/program.c12
-rw-r--r--src/util/scheduler.c1535
-rw-r--r--src/util/service.c31
-rw-r--r--src/util/time.c2
8 files changed, 1017 insertions, 659 deletions
diff --git a/src/util/client.c b/src/util/client.c
index 3d74bff33..e5bf7e176 100644
--- a/src/util/client.c
+++ b/src/util/client.c
@@ -261,14 +261,27 @@ transmit_ready (void *cls)
261 pos = (const char *) cstate->msg; 261 pos = (const char *) cstate->msg;
262 len = ntohs (cstate->msg->size); 262 len = ntohs (cstate->msg->size);
263 GNUNET_assert (cstate->msg_off < len); 263 GNUNET_assert (cstate->msg_off < len);
264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
265 "client: message of type %u trying to send with socket %p (MQ: %p\n",
266 ntohs(cstate->msg->type),
267 cstate->sock,
268 cstate->mq);
269
264 RETRY: 270 RETRY:
265 ret = GNUNET_NETWORK_socket_send (cstate->sock, 271 ret = GNUNET_NETWORK_socket_send (cstate->sock,
266 &pos[cstate->msg_off], 272 &pos[cstate->msg_off],
267 len - cstate->msg_off); 273 len - cstate->msg_off);
268 if (-1 == ret) 274 if (-1 == ret)
269 { 275 {
270 if (EINTR == errno) 276 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
277 "client: error during sending message of type %u\n",
278 ntohs(cstate->msg->type));
279 if (EINTR == errno){
280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
281 "client: retrying message of type %u\n",
282 ntohs(cstate->msg->type));
271 goto RETRY; 283 goto RETRY;
284 }
272 GNUNET_MQ_inject_error (cstate->mq, 285 GNUNET_MQ_inject_error (cstate->mq,
273 GNUNET_MQ_ERROR_WRITE); 286 GNUNET_MQ_ERROR_WRITE);
274 return; 287 return;
@@ -277,6 +290,9 @@ transmit_ready (void *cls)
277 cstate->msg_off += ret; 290 cstate->msg_off += ret;
278 if (cstate->msg_off < len) 291 if (cstate->msg_off < len)
279 { 292 {
293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
294 "client: rescheduling message of type %u\n",
295 ntohs(cstate->msg->type));
280 cstate->send_task 296 cstate->send_task
281 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, 297 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
282 cstate->sock, 298 cstate->sock,
@@ -286,6 +302,9 @@ transmit_ready (void *cls)
286 GNUNET_MQ_impl_send_in_flight (cstate->mq); 302 GNUNET_MQ_impl_send_in_flight (cstate->mq);
287 return; 303 return;
288 } 304 }
305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
306 "client: sending message of type %u successful\n",
307 ntohs(cstate->msg->type));
289 cstate->msg = NULL; 308 cstate->msg = NULL;
290 GNUNET_MQ_impl_send_continue (cstate->mq); 309 GNUNET_MQ_impl_send_continue (cstate->mq);
291} 310}
@@ -297,7 +316,9 @@ transmit_ready (void *cls)
297 * 316 *
298 * @param cls the `struct ClientState` 317 * @param cls the `struct ClientState`
299 * @param msg message we received. 318 * @param msg message we received.
300 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing 319 * @return #GNUNET_OK on success,
320 * #GNUNET_NO to stop further processing due to disconnect (no error)
321 * #GNUNET_SYSERR to stop further processing due to error
301 */ 322 */
302static int 323static int
303recv_message (void *cls, 324recv_message (void *cls,
@@ -306,7 +327,7 @@ recv_message (void *cls,
306 struct ClientState *cstate = cls; 327 struct ClientState *cstate = cls;
307 328
308 if (GNUNET_YES == cstate->in_destroy) 329 if (GNUNET_YES == cstate->in_destroy)
309 return GNUNET_SYSERR; 330 return GNUNET_NO;
310 LOG (GNUNET_ERROR_TYPE_DEBUG, 331 LOG (GNUNET_ERROR_TYPE_DEBUG,
311 "Received message of type %u and size %u from %s\n", 332 "Received message of type %u and size %u from %s\n",
312 ntohs (msg->type), 333 ntohs (msg->type),
@@ -315,7 +336,7 @@ recv_message (void *cls,
315 GNUNET_MQ_inject_message (cstate->mq, 336 GNUNET_MQ_inject_message (cstate->mq,
316 msg); 337 msg);
317 if (GNUNET_YES == cstate->in_destroy) 338 if (GNUNET_YES == cstate->in_destroy)
318 return GNUNET_SYSERR; 339 return GNUNET_NO;
319 return GNUNET_OK; 340 return GNUNET_OK;
320} 341}
321 342
@@ -371,8 +392,12 @@ connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq,
371 GNUNET_SCHEDULER_cancel (cstate->recv_task); 392 GNUNET_SCHEDULER_cancel (cstate->recv_task);
372 if (NULL != cstate->retry_task) 393 if (NULL != cstate->retry_task)
373 GNUNET_SCHEDULER_cancel (cstate->retry_task); 394 GNUNET_SCHEDULER_cancel (cstate->retry_task);
374 if (NULL != cstate->sock) 395 if (NULL != cstate->sock){
396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
397 "client: destroying socket: %p\n",
398 cstate->sock);
375 GNUNET_NETWORK_socket_close (cstate->sock); 399 GNUNET_NETWORK_socket_close (cstate->sock);
400 }
376 cancel_aps (cstate); 401 cancel_aps (cstate);
377 GNUNET_free (cstate->service_name); 402 GNUNET_free (cstate->service_name);
378 GNUNET_free_non_null (cstate->hostname); 403 GNUNET_free_non_null (cstate->hostname);
@@ -794,8 +819,12 @@ connection_client_send_impl (struct GNUNET_MQ_Handle *mq,
794 GNUNET_assert (NULL == cstate->send_task); 819 GNUNET_assert (NULL == cstate->send_task);
795 cstate->msg = msg; 820 cstate->msg = msg;
796 cstate->msg_off = 0; 821 cstate->msg_off = 0;
797 if (NULL == cstate->sock) 822 if (NULL == cstate->sock){
823 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
824 "client: message of type %u waiting for socket\n",
825 ntohs(msg->type));
798 return; /* still waiting for connection */ 826 return; /* still waiting for connection */
827 }
799 cstate->send_task 828 cstate->send_task
800 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, 829 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
801 cstate->sock, 830 cstate->sock,
diff --git a/src/util/mq.c b/src/util/mq.c
index 90b2aa968..8d71359ac 100644
--- a/src/util/mq.c
+++ b/src/util/mq.c
@@ -357,6 +357,12 @@ GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq,
357 } 357 }
358 GNUNET_assert (NULL == mq->envelope_head); 358 GNUNET_assert (NULL == mq->envelope_head);
359 mq->current_envelope = ev; 359 mq->current_envelope = ev;
360
361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
362 "mq: sending message of type %u, queue empty (MQ: %p)\n",
363 ntohs(ev->mh->type),
364 mq);
365
360 mq->send_impl (mq, 366 mq->send_impl (mq,
361 ev->mh, 367 ev->mh,
362 mq->impl_state); 368 mq->impl_state);
@@ -452,6 +458,11 @@ impl_send_continue (void *cls)
452 GNUNET_CONTAINER_DLL_remove (mq->envelope_head, 458 GNUNET_CONTAINER_DLL_remove (mq->envelope_head,
453 mq->envelope_tail, 459 mq->envelope_tail,
454 mq->current_envelope); 460 mq->current_envelope);
461
462 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
463 "mq: sending message of type %u from queue\n",
464 ntohs(mq->current_envelope->mh->type));
465
455 mq->send_impl (mq, 466 mq->send_impl (mq,
456 mq->current_envelope->mh, 467 mq->current_envelope->mh,
457 mq->impl_state); 468 mq->impl_state);
@@ -840,6 +851,9 @@ GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq)
840 ev); 851 ev);
841 GNUNET_assert (0 < mq->queue_length); 852 GNUNET_assert (0 < mq->queue_length);
842 mq->queue_length--; 853 mq->queue_length--;
854 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
855 "MQ destroy drops message of type %u\n",
856 ntohs (ev->mh->type));
843 GNUNET_MQ_discard (ev); 857 GNUNET_MQ_discard (ev);
844 } 858 }
845 if (NULL != mq->current_envelope) 859 if (NULL != mq->current_envelope)
@@ -847,6 +861,9 @@ GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq)
847 /* we can only discard envelopes that 861 /* we can only discard envelopes that
848 * are not queued! */ 862 * are not queued! */
849 mq->current_envelope->parent_queue = NULL; 863 mq->current_envelope->parent_queue = NULL;
864 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
865 "MQ destroy drops current message of type %u\n",
866 ntohs (mq->current_envelope->mh->type));
850 GNUNET_MQ_discard (mq->current_envelope); 867 GNUNET_MQ_discard (mq->current_envelope);
851 mq->current_envelope = NULL; 868 mq->current_envelope = NULL;
852 GNUNET_assert (0 < mq->queue_length); 869 GNUNET_assert (0 < mq->queue_length);
@@ -928,6 +945,11 @@ GNUNET_MQ_send_cancel (struct GNUNET_MQ_Envelope *ev)
928 GNUNET_CONTAINER_DLL_remove (mq->envelope_head, 945 GNUNET_CONTAINER_DLL_remove (mq->envelope_head,
929 mq->envelope_tail, 946 mq->envelope_tail,
930 mq->current_envelope); 947 mq->current_envelope);
948
949 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
950 "mq: sending canceled message of type %u queue\n",
951 ntohs(ev->mh->type));
952
931 mq->send_impl (mq, 953 mq->send_impl (mq,
932 mq->current_envelope->mh, 954 mq->current_envelope->mh,
933 mq->impl_state); 955 mq->impl_state);
diff --git a/src/util/mst.c b/src/util/mst.c
index 0d90c5d10..5e472965f 100644
--- a/src/util/mst.c
+++ b/src/util/mst.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2010, 2016 GNUnet e.V. 3 Copyright (C) 2010, 2016, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -126,6 +126,7 @@ GNUNET_MST_from_buffer (struct GNUNET_MessageStreamTokenizer *mst,
126 int need_align; 126 int need_align;
127 unsigned long offset; 127 unsigned long offset;
128 int ret; 128 int ret;
129 int cbret;
129 130
130 GNUNET_assert (mst->off <= mst->pos); 131 GNUNET_assert (mst->off <= mst->pos);
131 GNUNET_assert (mst->pos <= mst->curr_buf); 132 GNUNET_assert (mst->pos <= mst->curr_buf);
@@ -229,9 +230,17 @@ do_align:
229 if (one_shot == GNUNET_YES) 230 if (one_shot == GNUNET_YES)
230 one_shot = GNUNET_SYSERR; 231 one_shot = GNUNET_SYSERR;
231 mst->off += want; 232 mst->off += want;
232 if (GNUNET_SYSERR == mst->cb (mst->cb_cls, 233 if (GNUNET_OK !=
233 hdr)) 234 (cbret = mst->cb (mst->cb_cls,
235 hdr)))
236 {
237 if (GNUNET_SYSERR == cbret)
238 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
239 "Failure processing message of type %u and size %u\n",
240 ntohs (hdr->type),
241 ntohs (hdr->size));
234 return GNUNET_SYSERR; 242 return GNUNET_SYSERR;
243 }
235 if (mst->off == mst->pos) 244 if (mst->off == mst->pos)
236 { 245 {
237 /* reset to beginning of buffer, it's free right now! */ 246 /* reset to beginning of buffer, it's free right now! */
@@ -271,9 +280,17 @@ do_align:
271 } 280 }
272 if (one_shot == GNUNET_YES) 281 if (one_shot == GNUNET_YES)
273 one_shot = GNUNET_SYSERR; 282 one_shot = GNUNET_SYSERR;
274 if (GNUNET_SYSERR == mst->cb (mst->cb_cls, 283 if (GNUNET_OK !=
275 hdr)) 284 (cbret = mst->cb (mst->cb_cls,
285 hdr)))
286 {
287 if (GNUNET_SYSERR == cbret)
288 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
289 "Failure processing message of type %u and size %u\n",
290 ntohs (hdr->type),
291 ntohs (hdr->size));
276 return GNUNET_SYSERR; 292 return GNUNET_SYSERR;
293 }
277 buf += want; 294 buf += want;
278 size -= want; 295 size -= want;
279 } 296 }
diff --git a/src/util/network.c b/src/util/network.c
index 942288613..cf5ef3e00 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -1223,7 +1223,7 @@ GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
1223 * @return POSIX file descriptor 1223 * @return POSIX file descriptor
1224 */ 1224 */
1225int 1225int
1226GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc) 1226GNUNET_NETWORK_get_fd (const struct GNUNET_NETWORK_Handle *desc)
1227{ 1227{
1228 return desc->fd; 1228 return desc->fd;
1229} 1229}
@@ -1236,7 +1236,7 @@ GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
1236 * @return sockaddr 1236 * @return sockaddr
1237 */ 1237 */
1238struct sockaddr* 1238struct sockaddr*
1239GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc) 1239GNUNET_NETWORK_get_addr (const struct GNUNET_NETWORK_Handle *desc)
1240{ 1240{
1241 return desc->addr; 1241 return desc->addr;
1242} 1242}
@@ -1249,7 +1249,7 @@ GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1249 * @return socklen_t for sockaddr 1249 * @return socklen_t for sockaddr
1250 */ 1250 */
1251socklen_t 1251socklen_t
1252GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc) 1252GNUNET_NETWORK_get_addrlen (const struct GNUNET_NETWORK_Handle *desc)
1253{ 1253{
1254 return desc->addrlen; 1254 return desc->addrlen;
1255} 1255}
diff --git a/src/util/program.c b/src/util/program.c
index 92a9750f3..233792387 100644
--- a/src/util/program.c
+++ b/src/util/program.c
@@ -69,6 +69,16 @@ struct CommandContext
69 69
70 70
71/** 71/**
72 * task run when the scheduler shuts down
73 */
74static void
75shutdown_task (void *cls)
76{
77 GNUNET_SPEEDUP_stop_ ();
78}
79
80
81/**
72 * Initial task called by the scheduler for each 82 * Initial task called by the scheduler for each
73 * program. Runs the program-specific main task. 83 * program. Runs the program-specific main task.
74 */ 84 */
@@ -78,6 +88,7 @@ program_main (void *cls)
78 struct CommandContext *cc = cls; 88 struct CommandContext *cc = cls;
79 89
80 GNUNET_SPEEDUP_start_(cc->cfg); 90 GNUNET_SPEEDUP_start_(cc->cfg);
91 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
81 GNUNET_RESOLVER_connect (cc->cfg); 92 GNUNET_RESOLVER_connect (cc->cfg);
82 cc->task (cc->task_cls, cc->args, cc->cfgfile, cc->cfg); 93 cc->task (cc->task_cls, cc->args, cc->cfgfile, cc->cfg);
83} 94}
@@ -306,7 +317,6 @@ GNUNET_PROGRAM_run2 (int argc, char *const *argv, const char *binaryName,
306 } 317 }
307 ret = GNUNET_OK; 318 ret = GNUNET_OK;
308 cleanup: 319 cleanup:
309 GNUNET_SPEEDUP_stop_ ();
310 GNUNET_CONFIGURATION_destroy (cfg); 320 GNUNET_CONFIGURATION_destroy (cfg);
311 GNUNET_free_non_null (cc.cfgfile); 321 GNUNET_free_non_null (cc.cfgfile);
312 GNUNET_free (cfg_fn); 322 GNUNET_free (cfg_fn);
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index 540a60557..b96e4e6c4 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -89,12 +89,6 @@ struct GNUNET_SCHEDULER_Handle
89 * @deprecated 89 * @deprecated
90 */ 90 */
91 struct GNUNET_NETWORK_FDSet *ws; 91 struct GNUNET_NETWORK_FDSet *ws;
92
93 /**
94 * Driver we used for the event loop.
95 */
96 const struct GNUNET_SCHEDULER_Driver *driver;
97
98}; 92};
99 93
100 94
@@ -124,36 +118,40 @@ struct GNUNET_SCHEDULER_Task
124 void *callback_cls; 118 void *callback_cls;
125 119
126 /** 120 /**
127 * Handle to the scheduler's state. 121 * Information about which FDs are ready for this task (and why).
128 */ 122 */
129 const struct GNUNET_SCHEDULER_Handle *sh; 123 struct GNUNET_SCHEDULER_FdInfo *fds;
130 124
131 /** 125 /**
132 * Set of file descriptors this task is waiting 126 * Storage location used for @e fds if we want to avoid
133 * for for reading. Once ready, this is updated 127 * a separate malloc() call in the common case that this
134 * to reflect the set of file descriptors ready 128 * task is only about a single FD.
135 * for operation.
136 */ 129 */
137 struct GNUNET_NETWORK_FDSet *read_set; 130 struct GNUNET_SCHEDULER_FdInfo fdx;
138 131
139 /** 132 /**
140 * Set of file descriptors this task is waiting for for writing. 133 * Size of the @e fds array.
141 * Once ready, this is updated to reflect the set of file
142 * descriptors ready for operation.
143 */ 134 */
144 struct GNUNET_NETWORK_FDSet *write_set; 135 unsigned int fds_len;
145 136
146 /** 137 /**
147 * Information about which FDs are ready for this task (and why). 138 * if this task is related to multiple FDs this array contains
139 * all FdInfo structs that were marked as ready by calling
140 * #GNUNET_SCHEDULER_task_ready
148 */ 141 */
149 const struct GNUNET_SCHEDULER_FdInfo *fds; 142 struct GNUNET_SCHEDULER_FdInfo *ready_fds;
150 143
151 /** 144 /**
152 * Storage location used for @e fds if we want to avoid 145 * Size of the @e ready_fds array
153 * a separate malloc() call in the common case that this
154 * task is only about a single FD.
155 */ 146 */
156 struct GNUNET_SCHEDULER_FdInfo fdx; 147 unsigned int ready_fds_len;
148
149 /**
150 * Do we own the network and file handles referenced by the FdInfo
151 * structs in the fds array. This will only be GNUNET_YES if the
152 * task was created by the #GNUNET_SCHEDULER_add_select function.
153 */
154 int own_handles;
157 155
158 /** 156 /**
159 * Absolute timeout value for the task, or 157 * Absolute timeout value for the task, or
@@ -169,11 +167,6 @@ struct GNUNET_SCHEDULER_Task
169#endif 167#endif
170 168
171 /** 169 /**
172 * Size of the @e fds array.
173 */
174 unsigned int fds_len;
175
176 /**
177 * Why is the task ready? Set after task is added to ready queue. 170 * Why is the task ready? Set after task is added to ready queue.
178 * Initially set to zero. All reasons that have already been 171 * Initially set to zero. All reasons that have already been
179 * satisfied (i.e. read or write ready) will be set over time. 172 * satisfied (i.e. read or write ready) will be set over time.
@@ -224,11 +217,72 @@ struct GNUNET_SCHEDULER_Task
224 int num_backtrace_strings; 217 int num_backtrace_strings;
225#endif 218#endif
226 219
220};
221
222
223/**
224 * A struct representing an event the select driver is waiting for
225 */
226struct Scheduled
227{
228 struct Scheduled *prev;
229
230 struct Scheduled *next;
231
232 /**
233 * the task, the event is related to
234 */
235 struct GNUNET_SCHEDULER_Task *task;
236
237 /**
238 * information about the network socket / file descriptor where
239 * the event is expected to occur
240 */
241 struct GNUNET_SCHEDULER_FdInfo *fdi;
242
243 /**
244 * the event types (multiple event types can be ORed) the select
245 * driver is expected to wait for
246 */
247 enum GNUNET_SCHEDULER_EventType et;
248};
249
250
251/**
252 * Driver context used by GNUNET_SCHEDULER_run
253 */
254struct DriverContext
255{
256 /**
257 * the head of a DLL containing information about the events the
258 * select driver is waiting for
259 */
260 struct Scheduled *scheduled_head;
227 261
262 /**
263 * the tail of a DLL containing information about the events the
264 * select driver is waiting for
265 */
266 struct Scheduled *scheduled_tail;
267
268 /**
269 * the time until the select driver will wake up again (after
270 * calling select)
271 */
272 struct GNUNET_TIME_Relative timeout;
228}; 273};
229 274
230 275
231/** 276/**
277 * The driver used for the event loop. Will be handed over to
278 * the scheduler in #GNUNET_SCHEDULER_run_from_driver(), peristed
279 * there in this variable for later use in functions like
280 * #GNUNET_SCHEDULER_add_select(), #add_without_sets() and
281 * #GNUNET_SCHEDULER_cancel().
282 */
283static const struct GNUNET_SCHEDULER_Driver *scheduler_driver;
284
285/**
232 * Head of list of tasks waiting for an event. 286 * Head of list of tasks waiting for an event.
233 */ 287 */
234static struct GNUNET_SCHEDULER_Task *pending_head; 288static struct GNUNET_SCHEDULER_Task *pending_head;
@@ -330,6 +384,11 @@ static struct GNUNET_SCHEDULER_TaskContext tc;
330 */ 384 */
331static void *scheduler_select_cls; 385static void *scheduler_select_cls;
332 386
387/**
388 * Scheduler handle used for the driver functions
389 */
390static struct GNUNET_SCHEDULER_Handle sh;
391
333 392
334/** 393/**
335 * Sets the select function to use in the scheduler (scheduler_select). 394 * Sets the select function to use in the scheduler (scheduler_select).
@@ -364,115 +423,44 @@ check_priority (enum GNUNET_SCHEDULER_Priority p)
364 423
365 424
366/** 425/**
367 * Update all sets and timeout for select. 426 * chooses the nearest timeout from all pending tasks, to be used
368 * 427 * to tell the driver the next wakeup time (using its set_wakeup
369 * @param rs read-set, set to all FDs we would like to read (updated) 428 * callback)
370 * @param ws write-set, set to all FDs we would like to write (updated)
371 * @param timeout next timeout (updated)
372 */ 429 */
373static void 430struct GNUNET_TIME_Absolute
374update_sets (struct GNUNET_NETWORK_FDSet *rs, 431get_timeout ()
375 struct GNUNET_NETWORK_FDSet *ws,
376 struct GNUNET_TIME_Relative *timeout)
377{ 432{
378 struct GNUNET_SCHEDULER_Task *pos; 433 struct GNUNET_SCHEDULER_Task *pos;
379 struct GNUNET_TIME_Absolute now; 434 struct GNUNET_TIME_Absolute now;
380 struct GNUNET_TIME_Relative to; 435 struct GNUNET_TIME_Absolute timeout;
381 436
382 now = GNUNET_TIME_absolute_get ();
383 pos = pending_timeout_head; 437 pos = pending_timeout_head;
438 now = GNUNET_TIME_absolute_get ();
439 timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
384 if (NULL != pos) 440 if (NULL != pos)
385 { 441 {
386 to = GNUNET_TIME_absolute_get_difference (now, pos->timeout);
387 if (timeout->rel_value_us > to.rel_value_us)
388 *timeout = to;
389 if (0 != pos->reason) 442 if (0 != pos->reason)
390 *timeout = GNUNET_TIME_UNIT_ZERO; 443 {
444 timeout = now;
445 }
446 else
447 {
448 timeout = pos->timeout;
449 }
391 } 450 }
392 for (pos = pending_head; NULL != pos; pos = pos->next) 451 for (pos = pending_head; NULL != pos; pos = pos->next)
393 { 452 {
394 if (pos->timeout.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) 453 if (0 != pos->reason)
395 { 454 {
396 to = GNUNET_TIME_absolute_get_difference (now, pos->timeout); 455 timeout = now;
397 if (timeout->rel_value_us > to.rel_value_us) 456 }
398 *timeout = to; 457 else if ((pos->timeout.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) &&
458 (timeout.abs_value_us > pos->timeout.abs_value_us))
459 {
460 timeout = pos->timeout;
399 } 461 }
400 if (-1 != pos->read_fd)
401 GNUNET_NETWORK_fdset_set_native (rs, pos->read_fd);
402 if (-1 != pos->write_fd)
403 GNUNET_NETWORK_fdset_set_native (ws, pos->write_fd);
404 if (NULL != pos->read_set)
405 GNUNET_NETWORK_fdset_add (rs, pos->read_set);
406 if (NULL != pos->write_set)
407 GNUNET_NETWORK_fdset_add (ws, pos->write_set);
408 if (0 != pos->reason)
409 *timeout = GNUNET_TIME_UNIT_ZERO;
410 }
411}
412
413
414/**
415 * Check if the ready set overlaps with the set we want to have ready.
416 * If so, update the want set (set all FDs that are ready). If not,
417 * return #GNUNET_NO.
418 *
419 * @param ready set that is ready
420 * @param want set that we want to be ready
421 * @return #GNUNET_YES if there was some overlap
422 */
423static int
424set_overlaps (const struct GNUNET_NETWORK_FDSet *ready,
425 struct GNUNET_NETWORK_FDSet *want)
426{
427 if ((NULL == want) || (NULL == ready))
428 return GNUNET_NO;
429 if (GNUNET_NETWORK_fdset_overlap (ready, want))
430 {
431 /* copy all over (yes, there maybe unrelated bits,
432 * but this should not hurt well-written clients) */
433 GNUNET_NETWORK_fdset_copy (want, ready);
434 return GNUNET_YES;
435 } 462 }
436 return GNUNET_NO; 463 return timeout;
437}
438
439
440/**
441 * Check if the given task is eligible to run now.
442 * Also set the reason why it is eligible.
443 *
444 * @param task task to check if it is ready
445 * @param now the current time
446 * @param rs set of FDs ready for reading
447 * @param ws set of FDs ready for writing
448 * @return #GNUNET_YES if we can run it, #GNUNET_NO if not.
449 */
450static int
451is_ready (struct GNUNET_SCHEDULER_Task *task,
452 struct GNUNET_TIME_Absolute now,
453 const struct GNUNET_NETWORK_FDSet *rs,
454 const struct GNUNET_NETWORK_FDSet *ws)
455{
456 enum GNUNET_SCHEDULER_Reason reason;
457
458 reason = task->reason;
459 if (now.abs_value_us >= task->timeout.abs_value_us)
460 reason |= GNUNET_SCHEDULER_REASON_TIMEOUT;
461 if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
462 (((task->read_fd != -1) &&
463 (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (rs, task->read_fd))) ||
464 (set_overlaps (rs, task->read_set))))
465 reason |= GNUNET_SCHEDULER_REASON_READ_READY;
466 if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
467 (((task->write_fd != -1) &&
468 (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (ws, task->write_fd)))
469 || (set_overlaps (ws, task->write_set))))
470 reason |= GNUNET_SCHEDULER_REASON_WRITE_READY;
471 if (0 == reason)
472 return GNUNET_NO; /* not ready */
473 reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE;
474 task->reason = reason;
475 return GNUNET_YES;
476} 464}
477 465
478 466
@@ -495,51 +483,6 @@ queue_ready_task (struct GNUNET_SCHEDULER_Task *task)
495 483
496 484
497/** 485/**
498 * Check which tasks are ready and move them
499 * to the respective ready queue.
500 *
501 * @param rs FDs ready for reading
502 * @param ws FDs ready for writing
503 */
504static void
505check_ready (const struct GNUNET_NETWORK_FDSet *rs,
506 const struct GNUNET_NETWORK_FDSet *ws)
507{
508 struct GNUNET_SCHEDULER_Task *pos;
509 struct GNUNET_SCHEDULER_Task *next;
510 struct GNUNET_TIME_Absolute now;
511
512 now = GNUNET_TIME_absolute_get ();
513 while (NULL != (pos = pending_timeout_head))
514 {
515 if (now.abs_value_us >= pos->timeout.abs_value_us)
516 pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT;
517 if (0 == pos->reason)
518 break;
519 GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
520 pending_timeout_tail,
521 pos);
522 if (pending_timeout_last == pos)
523 pending_timeout_last = NULL;
524 queue_ready_task (pos);
525 }
526 pos = pending_head;
527 while (NULL != pos)
528 {
529 next = pos->next;
530 if (GNUNET_YES == is_ready (pos, now, rs, ws))
531 {
532 GNUNET_CONTAINER_DLL_remove (pending_head,
533 pending_tail,
534 pos);
535 queue_ready_task (pos);
536 }
537 pos = next;
538 }
539}
540
541
542/**
543 * Request the shutdown of a scheduler. Marks all tasks 486 * Request the shutdown of a scheduler. Marks all tasks
544 * awaiting shutdown as ready. Note that tasks 487 * awaiting shutdown as ready. Note that tasks
545 * scheduled with #GNUNET_SCHEDULER_add_shutdown() AFTER this call 488 * scheduled with #GNUNET_SCHEDULER_add_shutdown() AFTER this call
@@ -562,25 +505,6 @@ GNUNET_SCHEDULER_shutdown ()
562 505
563 506
564/** 507/**
565 * Destroy a task (release associated resources)
566 *
567 * @param t task to destroy
568 */
569static void
570destroy_task (struct GNUNET_SCHEDULER_Task *t)
571{
572 if (NULL != t->read_set)
573 GNUNET_NETWORK_fdset_destroy (t->read_set);
574 if (NULL != t->write_set)
575 GNUNET_NETWORK_fdset_destroy (t->write_set);
576#if EXECINFO
577 GNUNET_free (t->backtrace_strings);
578#endif
579 GNUNET_free (t);
580}
581
582
583/**
584 * Output stack trace of task @a t. 508 * Output stack trace of task @a t.
585 * 509 *
586 * @param t task to dump stack trace of 510 * @param t task to dump stack trace of
@@ -592,88 +516,59 @@ dump_backtrace (struct GNUNET_SCHEDULER_Task *t)
592 unsigned int i; 516 unsigned int i;
593 517
594 for (i = 0; i < t->num_backtrace_strings; i++) 518 for (i = 0; i < t->num_backtrace_strings; i++)
595 LOG (GNUNET_ERROR_TYPE_DEBUG, 519 LOG (GNUNET_ERROR_TYPE_WARNING,
596 "Task %p trace %u: %s\n", 520 "Task %p trace %u: %s\n",
597 t, 521 t,
598 i, 522 i,
599 t->backtrace_strings[i]); 523 t->backtrace_strings[i]);
600#endif 524#endif
601} 525}
602 526
603 527
604/** 528/**
605 * Run at least one task in the highest-priority queue that is not 529 * Destroy a task (release associated resources)
606 * empty. Keep running tasks until we are either no longer running
607 * "URGENT" tasks or until we have at least one "pending" task (which
608 * may become ready, hence we should select on it). Naturally, if
609 * there are no more ready tasks, we also return.
610 * 530 *
611 * @param rs FDs ready for reading 531 * @param t task to destroy
612 * @param ws FDs ready for writing
613 */ 532 */
614static void 533static void
615run_ready (struct GNUNET_NETWORK_FDSet *rs, 534destroy_task (struct GNUNET_SCHEDULER_Task *t)
616 struct GNUNET_NETWORK_FDSet *ws)
617{ 535{
618 enum GNUNET_SCHEDULER_Priority p; 536 unsigned int i;
619 struct GNUNET_SCHEDULER_Task *pos;
620 537
621 max_priority_added = GNUNET_SCHEDULER_PRIORITY_KEEP; 538 LOG (GNUNET_ERROR_TYPE_DEBUG,
622 do 539 "destroying task %p\n",
540 t);
541
542 if (GNUNET_YES == t->own_handles)
623 { 543 {
624 if (0 == ready_count) 544 for (i = 0; i != t->fds_len; ++i)
625 return;
626 GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]);
627 /* yes, p>0 is correct, 0 is "KEEP" which should
628 * always be an empty queue (see assertion)! */
629 for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--)
630 {
631 pos = ready_head[p];
632 if (NULL != pos)
633 break;
634 }
635 GNUNET_assert (NULL != pos); /* ready_count wrong? */
636 GNUNET_CONTAINER_DLL_remove (ready_head[p],
637 ready_tail[p],
638 pos);
639 ready_count--;
640 current_priority = pos->priority;
641 current_lifeness = pos->lifeness;
642 active_task = pos;
643#if PROFILE_DELAYS
644 if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
645 DELAY_THRESHOLD.rel_value_us)
646 { 545 {
647 LOG (GNUNET_ERROR_TYPE_DEBUG, 546 const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
648 "Task %p took %s to be scheduled\n", 547 const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
649 pos, 548 if (fd)
650 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), 549 {
651 GNUNET_YES)); 550 GNUNET_NETWORK_socket_free_memory_only_ ((struct GNUNET_NETWORK_Handle *) fd);
551 }
552 if (fh)
553 {
554 // FIXME: on WIN32 this is not enough! A function
555 // GNUNET_DISK_file_free_memory_only would be nice
556 GNUNET_free ((void *) fh);
557 }
652 } 558 }
653#endif
654 tc.reason = pos->reason;
655 tc.read_ready = (NULL == pos->read_set) ? rs : pos->read_set;
656 if ((-1 != pos->read_fd) &&
657 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)))
658 GNUNET_NETWORK_fdset_set_native (rs, pos->read_fd);
659 tc.write_ready = (NULL == pos->write_set) ? ws : pos->write_set;
660 if ((-1 != pos->write_fd) &&
661 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)))
662 GNUNET_NETWORK_fdset_set_native (ws, pos->write_fd);
663 if ((0 != (tc.reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
664 (-1 != pos->write_fd) &&
665 (!GNUNET_NETWORK_fdset_test_native (ws, pos->write_fd)))
666 GNUNET_assert (0); // added to ready in previous select loop!
667 LOG (GNUNET_ERROR_TYPE_DEBUG,
668 "Running task: %p\n",
669 pos);
670 pos->callback (pos->callback_cls);
671 dump_backtrace (pos);
672 active_task = NULL;
673 destroy_task (pos);
674 tasks_run++;
675 } 559 }
676 while ((NULL == pending_head) || (p >= max_priority_added)); 560 if (t->fds_len > 1)
561 {
562 GNUNET_array_grow (t->fds, t->fds_len, 0);
563 }
564 if (t->ready_fds_len > 0)
565 {
566 GNUNET_array_grow (t->ready_fds, t->ready_fds_len, 0);
567 }
568#if EXECINFO
569 GNUNET_free (t->backtrace_strings);
570#endif
571 GNUNET_free (t);
677} 572}
678 573
679 574
@@ -700,22 +595,22 @@ sighandler_pipe ()
700#endif 595#endif
701 596
702 597
703/** 598///**
704 * Wait for a short time. 599// * Wait for a short time.
705 * Sleeps for @a ms ms (as that should be long enough for virtually all 600// * Sleeps for @a ms ms (as that should be long enough for virtually all
706 * modern systems to context switch and allow another process to do 601// * modern systems to context switch and allow another process to do
707 * some 'real' work). 602// * some 'real' work).
708 * 603// *
709 * @param ms how many ms to wait 604// * @param ms how many ms to wait
710 */ 605// */
711static void 606//static void
712short_wait (unsigned int ms) 607//short_wait (unsigned int ms)
713{ 608//{
714 struct GNUNET_TIME_Relative timeout; 609// struct GNUNET_TIME_Relative timeout;
715 610//
716 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms); 611// timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms);
717 (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout); 612// (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
718} 613//}
719 614
720 615
721/** 616/**
@@ -737,35 +632,31 @@ sighandler_shutdown ()
737} 632}
738 633
739 634
740/** 635void
741 * Check if the system is still alive. Trigger shutdown if we 636shutdown_if_no_lifeness ()
742 * have tasks, but none of them give us lifeness.
743 *
744 * @return #GNUNET_OK to continue the main loop,
745 * #GNUNET_NO to exit
746 */
747static int
748check_lifeness ()
749{ 637{
750 struct GNUNET_SCHEDULER_Task *t; 638 struct GNUNET_SCHEDULER_Task *t;
751 639
752 if (ready_count > 0) 640 if (ready_count > 0)
753 return GNUNET_OK; 641 return;
754 for (t = pending_head; NULL != t; t = t->next) 642 for (t = pending_head; NULL != t; t = t->next)
755 if (t->lifeness == GNUNET_YES) 643 if (GNUNET_YES == t->lifeness)
756 return GNUNET_OK; 644 return;
757 for (t = shutdown_head; NULL != t; t = t->next) 645 for (t = shutdown_head; NULL != t; t = t->next)
758 if (t->lifeness == GNUNET_YES) 646 if (GNUNET_YES == t->lifeness)
759 return GNUNET_OK; 647 return;
760 for (t = pending_timeout_head; NULL != t; t = t->next) 648 for (t = pending_timeout_head; NULL != t; t = t->next)
761 if (t->lifeness == GNUNET_YES) 649 if (GNUNET_YES == t->lifeness)
762 return GNUNET_OK; 650 return;
763 if (NULL != shutdown_head) 651 /* No lifeness! Cancel all pending tasks the driver knows about and shutdown */
652 t = pending_head;
653 while (NULL != t)
764 { 654 {
765 GNUNET_SCHEDULER_shutdown (); 655 struct GNUNET_SCHEDULER_Task *next = t->next;
766 return GNUNET_OK; 656 GNUNET_SCHEDULER_cancel (t);
657 t = next;
767 } 658 }
768 return GNUNET_NO; 659 GNUNET_SCHEDULER_shutdown ();
769} 660}
770 661
771 662
@@ -787,204 +678,17 @@ void
787GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, 678GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task,
788 void *task_cls) 679 void *task_cls)
789{ 680{
790 GNUNET_SCHEDULER_run_with_optional_signals(GNUNET_YES, task, task_cls); 681 struct GNUNET_SCHEDULER_Driver *driver;
791} 682 struct DriverContext context = {.scheduled_head = NULL,
792 683 .scheduled_tail = NULL,
793void 684 .timeout = GNUNET_TIME_UNIT_FOREVER_REL};
794GNUNET_SCHEDULER_run_with_optional_signals (int install_signals, 685
795 GNUNET_SCHEDULER_TaskCallback task, 686 driver = GNUNET_SCHEDULER_driver_select ();
796 void *task_cls) 687 driver->cls = &context;
797{ 688
798 struct GNUNET_NETWORK_FDSet *rs; 689 GNUNET_SCHEDULER_run_with_driver (driver, task, task_cls);
799 struct GNUNET_NETWORK_FDSet *ws; 690
800 struct GNUNET_TIME_Relative timeout; 691 GNUNET_free (driver);
801 int ret;
802 struct GNUNET_SIGNAL_Context *shc_int;
803 struct GNUNET_SIGNAL_Context *shc_term;
804#if (SIGTERM != GNUNET_TERM_SIG)
805 struct GNUNET_SIGNAL_Context *shc_gterm;
806#endif
807
808#ifndef MINGW
809 struct GNUNET_SIGNAL_Context *shc_quit;
810 struct GNUNET_SIGNAL_Context *shc_hup;
811 struct GNUNET_SIGNAL_Context *shc_pipe;
812#endif
813 unsigned long long last_tr;
814 unsigned int busy_wait_warning;
815 const struct GNUNET_DISK_FileHandle *pr;
816 char c;
817
818 GNUNET_assert (NULL == active_task);
819 rs = GNUNET_NETWORK_fdset_create ();
820 ws = GNUNET_NETWORK_fdset_create ();
821 GNUNET_assert (NULL == shutdown_pipe_handle);
822 shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO,
823 GNUNET_NO,
824 GNUNET_NO,
825 GNUNET_NO);
826 GNUNET_assert (NULL != shutdown_pipe_handle);
827 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
828 GNUNET_DISK_PIPE_END_READ);
829 GNUNET_assert (NULL != pr);
830 my_pid = getpid ();
831
832 if (GNUNET_YES == install_signals)
833 {
834 LOG (GNUNET_ERROR_TYPE_DEBUG,
835 "Registering signal handlers\n");
836 shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
837 &sighandler_shutdown);
838 shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
839 &sighandler_shutdown);
840#if (SIGTERM != GNUNET_TERM_SIG)
841 shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG,
842 &sighandler_shutdown);
843#endif
844#ifndef MINGW
845 shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
846 &sighandler_pipe);
847 shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
848 &sighandler_shutdown);
849 shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
850 &sighandler_shutdown);
851#endif
852 }
853
854 current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT;
855 current_lifeness = GNUNET_YES;
856 GNUNET_SCHEDULER_add_with_reason_and_priority (task,
857 task_cls,
858 GNUNET_SCHEDULER_REASON_STARTUP,
859 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
860 active_task = (void *) (long) -1; /* force passing of sanity check */
861 GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO,
862 &GNUNET_OS_install_parent_control_handler,
863 NULL);
864 active_task = NULL;
865 last_tr = 0;
866 busy_wait_warning = 0;
867 while (GNUNET_OK == check_lifeness ())
868 {
869 GNUNET_NETWORK_fdset_zero (rs);
870 GNUNET_NETWORK_fdset_zero (ws);
871 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
872 update_sets (rs, ws, &timeout);
873 GNUNET_NETWORK_fdset_handle_set (rs, pr);
874 if (ready_count > 0)
875 {
876 /* no blocking, more work already ready! */
877 timeout = GNUNET_TIME_UNIT_ZERO;
878 }
879 if (NULL == scheduler_select)
880 ret = GNUNET_NETWORK_socket_select (rs,
881 ws,
882 NULL,
883 timeout);
884 else
885 ret = scheduler_select (scheduler_select_cls,
886 rs,
887 ws,
888 NULL,
889 timeout);
890 if (ret == GNUNET_SYSERR)
891 {
892 if (errno == EINTR)
893 continue;
894
895 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "select");
896#ifndef MINGW
897#if USE_LSOF
898 char lsof[512];
899
900 snprintf (lsof, sizeof (lsof), "lsof -p %d", getpid ());
901 (void) close (1);
902 (void) dup2 (2, 1);
903 if (0 != system (lsof))
904 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
905 "system");
906#endif
907#endif
908#if DEBUG_FDS
909 struct GNUNET_SCHEDULER_Task *t;
910
911 for (t = pending_head; NULL != t; t = t->next)
912 {
913 if (-1 != t->read_fd)
914 {
915 int flags = fcntl (t->read_fd, F_GETFD);
916 if ((flags == -1) && (errno == EBADF))
917 {
918 LOG (GNUNET_ERROR_TYPE_ERROR,
919 "Got invalid file descriptor %d!\n",
920 t->read_fd);
921 dump_backtrace (t);
922 }
923 }
924 if (-1 != t->write_fd)
925 {
926 int flags = fcntl (t->write_fd, F_GETFD);
927 if ((flags == -1) && (errno == EBADF))
928 {
929 LOG (GNUNET_ERROR_TYPE_ERROR,
930 "Got invalid file descriptor %d!\n",
931 t->write_fd);
932 dump_backtrace (t);
933 }
934 }
935 }
936#endif
937 GNUNET_assert (0);
938 break;
939 }
940
941 if ( (0 == ret) &&
942 (0 == timeout.rel_value_us) &&
943 (busy_wait_warning > 16) )
944 {
945 LOG (GNUNET_ERROR_TYPE_WARNING,
946 "Looks like we're busy waiting...\n");
947 short_wait (100); /* mitigate */
948 }
949 check_ready (rs, ws);
950 run_ready (rs, ws);
951 if (GNUNET_NETWORK_fdset_handle_isset (rs, pr))
952 {
953 /* consume the signal */
954 GNUNET_DISK_file_read (pr, &c, sizeof (c));
955 /* mark all active tasks as ready due to shutdown */
956 GNUNET_SCHEDULER_shutdown ();
957 }
958 if (last_tr == tasks_run)
959 {
960 short_wait (1);
961 busy_wait_warning++;
962 }
963 else
964 {
965 last_tr = tasks_run;
966 busy_wait_warning = 0;
967 }
968 }
969
970 if (GNUNET_YES == install_signals)
971 {
972 GNUNET_SIGNAL_handler_uninstall (shc_int);
973 GNUNET_SIGNAL_handler_uninstall (shc_term);
974#if (SIGTERM != GNUNET_TERM_SIG)
975 GNUNET_SIGNAL_handler_uninstall (shc_gterm);
976#endif
977#ifndef MINGW
978 GNUNET_SIGNAL_handler_uninstall (shc_pipe);
979 GNUNET_SIGNAL_handler_uninstall (shc_quit);
980 GNUNET_SIGNAL_handler_uninstall (shc_hup);
981#endif
982 }
983
984 GNUNET_DISK_pipe_close (shutdown_pipe_handle);
985 shutdown_pipe_handle = NULL;
986 GNUNET_NETWORK_fdset_destroy (rs);
987 GNUNET_NETWORK_fdset_destroy (ws);
988} 692}
989 693
990 694
@@ -1029,9 +733,164 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p)
1029} 733}
1030 734
1031 735
736void
737init_fd_info (struct GNUNET_SCHEDULER_Task *t,
738 const struct GNUNET_NETWORK_Handle *const *read_nh,
739 unsigned int read_nh_len,
740 const struct GNUNET_NETWORK_Handle *const *write_nh,
741 unsigned int write_nh_len,
742 const struct GNUNET_DISK_FileHandle *const *read_fh,
743 unsigned int read_fh_len,
744 const struct GNUNET_DISK_FileHandle *const *write_fh,
745 unsigned int write_fh_len)
746{
747 // FIXME: if we have exactly two network handles / exactly two file handles
748 // and they are equal, we can make one FdInfo with both
749 // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
750 struct GNUNET_SCHEDULER_FdInfo *fdi;
751
752 t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
753 if (1 == t->fds_len)
754 {
755 fdi = &t->fdx;
756 t->fds = fdi;
757 if (1 == read_nh_len)
758 {
759 fdi->fd = *read_nh;
760 GNUNET_assert (NULL != fdi->fd);
761 fdi->et = GNUNET_SCHEDULER_ET_IN;
762 fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
763 t->read_fd = fdi->sock;
764 t->write_fd = -1;
765 }
766 else if (1 == write_nh_len)
767 {
768 fdi->fd = *write_nh;
769 GNUNET_assert (NULL != fdi->fd);
770 fdi->et = GNUNET_SCHEDULER_ET_OUT;
771 fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
772 t->read_fd = -1;
773 t->write_fd = fdi->sock;
774 }
775 else if (1 == read_fh_len)
776 {
777 fdi->fh = *read_fh;
778 GNUNET_assert (NULL != fdi->fh);
779 fdi->et = GNUNET_SCHEDULER_ET_IN;
780 fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
781 t->read_fd = fdi->sock;
782 t->write_fd = -1;
783 }
784 else
785 {
786 fdi->fh = *write_fh;
787 GNUNET_assert (NULL != fdi->fh);
788 fdi->et = GNUNET_SCHEDULER_ET_OUT;
789 fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
790 t->read_fd = -1;
791 t->write_fd = fdi->sock;
792 }
793 }
794 else
795 {
796 fdi = GNUNET_new_array (t->fds_len, struct GNUNET_SCHEDULER_FdInfo);
797 t->fds = fdi;
798 t->read_fd = -1;
799 t->write_fd = -1;
800 unsigned int i;
801 for (i = 0; i != read_nh_len; ++i)
802 {
803 fdi->fd = read_nh[i];
804 GNUNET_assert (NULL != fdi->fd);
805 fdi->et = GNUNET_SCHEDULER_ET_IN;
806 fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
807 ++fdi;
808 }
809 for (i = 0; i != write_nh_len; ++i)
810 {
811 fdi->fd = write_nh[i];
812 GNUNET_assert (NULL != fdi->fd);
813 fdi->et = GNUNET_SCHEDULER_ET_OUT;
814 fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
815 ++fdi;
816 }
817 for (i = 0; i != read_fh_len; ++i)
818 {
819 fdi->fh = read_fh[i];
820 GNUNET_assert (NULL != fdi->fh);
821 fdi->et = GNUNET_SCHEDULER_ET_IN;
822 fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
823 ++fdi;
824 }
825 for (i = 0; i != write_fh_len; ++i)
826 {
827 fdi->fh = write_fh[i];
828 GNUNET_assert (NULL != fdi->fh);
829 fdi->et = GNUNET_SCHEDULER_ET_OUT;
830 fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
831 ++fdi;
832 }
833 }
834}
835
836
837/**
838 * calls the given function @a func on each FdInfo related to @a t.
839 * Optionally updates the event type field in each FdInfo after calling
840 * @a func.
841 *
842 * @param t the task
843 * @param driver_func the function to call with each FdInfo contained in
844 * in @a t
845 * @param if_not_ready only call @a driver_func on FdInfos that are not
846 * ready
847 * @param et the event type to be set in each FdInfo after calling
848 * @a driver_func on it, or -1 if no updating not desired.
849 */
850void driver_add_multiple (struct GNUNET_SCHEDULER_Task *t,
851 enum GNUNET_SCHEDULER_EventType et)
852{
853 struct GNUNET_SCHEDULER_FdInfo *fdi;
854 int success = GNUNET_YES;
855
856 for (int i = 0; i != t->fds_len; ++i)
857 {
858 fdi = &t->fds[i];
859 success = scheduler_driver->add (scheduler_driver->cls, t, fdi) && success;
860 if (et != -1)
861 {
862 fdi->et = et;
863 }
864 }
865 if (GNUNET_YES != success)
866 {
867 LOG (GNUNET_ERROR_TYPE_ERROR,
868 "driver could not add task\n");
869 }
870}
871
872
873void
874shutdown_cb (void *cls)
875{
876 char c;
877 const struct GNUNET_DISK_FileHandle *pr;
878
879 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
880 GNUNET_DISK_PIPE_END_READ);
881 GNUNET_assert (! GNUNET_DISK_handle_invalid (pr));
882 /* consume the signal */
883 GNUNET_DISK_file_read (pr, &c, sizeof (c));
884 /* mark all active tasks as ready due to shutdown */
885 GNUNET_SCHEDULER_shutdown ();
886}
887
888
1032/** 889/**
1033 * Cancel the task with the specified identifier. 890 * Cancel the task with the specified identifier.
1034 * The task must not yet have run. 891 * The task must not yet have run. Only allowed to be called as long as the
892 * scheduler is running (#GNUNET_SCHEDULER_run or
893 * #GNUNET_SCHEDULER_run_with_driver has been called and has not returned yet).
1035 * 894 *
1036 * @param task id of the task to cancel 895 * @param task id of the task to cancel
1037 * @return original closure of the task 896 * @return original closure of the task
@@ -1040,34 +899,50 @@ void *
1040GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) 899GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task)
1041{ 900{
1042 enum GNUNET_SCHEDULER_Priority p; 901 enum GNUNET_SCHEDULER_Priority p;
902 int is_fd_task;
1043 void *ret; 903 void *ret;
1044 904
905 LOG (GNUNET_ERROR_TYPE_DEBUG,
906 "canceling task %p\n",
907 task);
908
909 /* scheduler must be running */
910 GNUNET_assert (NULL != scheduler_driver);
1045 GNUNET_assert ( (NULL != active_task) || 911 GNUNET_assert ( (NULL != active_task) ||
1046 (GNUNET_NO == task->lifeness) ); 912 (GNUNET_NO == task->lifeness) );
1047 if (! task->in_ready_list) 913 is_fd_task = (NULL != task->fds);
914 if (is_fd_task)
1048 { 915 {
1049 if ( (-1 == task->read_fd) && 916 int del_result = scheduler_driver->del (scheduler_driver->cls, task);
1050 (-1 == task->write_fd) && 917 if (GNUNET_OK != del_result)
1051 (NULL == task->read_set) &&
1052 (NULL == task->write_set) )
1053 { 918 {
1054 if (GNUNET_YES == task->on_shutdown) 919 LOG (GNUNET_ERROR_TYPE_ERROR,
1055 GNUNET_CONTAINER_DLL_remove (shutdown_head, 920 "driver could not delete task\n");
1056 shutdown_tail, 921 GNUNET_assert (0);
1057 task);
1058 else
1059 GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
1060 pending_timeout_tail,
1061 task);
1062 if (task == pending_timeout_last)
1063 pending_timeout_last = NULL;
1064 } 922 }
1065 else 923 }
924 if (! task->in_ready_list)
925 {
926 if (is_fd_task)
1066 { 927 {
1067 GNUNET_CONTAINER_DLL_remove (pending_head, 928 GNUNET_CONTAINER_DLL_remove (pending_head,
1068 pending_tail, 929 pending_tail,
1069 task); 930 task);
1070 } 931 }
932 else if (GNUNET_YES == task->on_shutdown)
933 {
934 GNUNET_CONTAINER_DLL_remove (shutdown_head,
935 shutdown_tail,
936 task);
937 }
938 else
939 {
940 GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
941 pending_timeout_tail,
942 task);
943 if (pending_timeout_last == task)
944 pending_timeout_last = NULL;
945 }
1071 } 946 }
1072 else 947 else
1073 { 948 {
@@ -1078,9 +953,6 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task)
1078 ready_count--; 953 ready_count--;
1079 } 954 }
1080 ret = task->callback_cls; 955 ret = task->callback_cls;
1081 LOG (GNUNET_ERROR_TYPE_DEBUG,
1082 "Canceling task %p\n",
1083 task);
1084 destroy_task (task); 956 destroy_task (task);
1085 return ret; 957 return ret;
1086} 958}
@@ -1101,7 +973,7 @@ init_backtrace (struct GNUNET_SCHEDULER_Task *t)
1101 = backtrace (backtrace_array, MAX_TRACE_DEPTH); 973 = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1102 t->backtrace_strings = 974 t->backtrace_strings =
1103 backtrace_symbols (backtrace_array, 975 backtrace_symbols (backtrace_array,
1104 t->num_backtrace_strings); 976 t->num_backtrace_strings);
1105 dump_backtrace (t); 977 dump_backtrace (t);
1106#endif 978#endif
1107} 979}
@@ -1218,7 +1090,7 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at,
1218 pending_timeout_last = t; 1090 pending_timeout_last = t;
1219 1091
1220 LOG (GNUNET_ERROR_TYPE_DEBUG, 1092 LOG (GNUNET_ERROR_TYPE_DEBUG,
1221 "Adding task: %p\n", 1093 "Adding task %p\n",
1222 t); 1094 t);
1223 init_backtrace (t); 1095 init_backtrace (t);
1224 return t; 1096 return t;
@@ -1238,8 +1110,8 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at,
1238 */ 1110 */
1239struct GNUNET_SCHEDULER_Task * 1111struct GNUNET_SCHEDULER_Task *
1240GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, 1112GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay,
1241 enum GNUNET_SCHEDULER_Priority priority, 1113 enum GNUNET_SCHEDULER_Priority priority,
1242 GNUNET_SCHEDULER_TaskCallback task, 1114 GNUNET_SCHEDULER_TaskCallback task,
1243 void *task_cls) 1115 void *task_cls)
1244{ 1116{
1245 return GNUNET_SCHEDULER_add_at_with_priority (GNUNET_TIME_relative_to_absolute (delay), 1117 return GNUNET_SCHEDULER_add_at_with_priority (GNUNET_TIME_relative_to_absolute (delay),
@@ -1307,12 +1179,12 @@ GNUNET_SCHEDULER_add_at (struct GNUNET_TIME_Absolute at,
1307struct GNUNET_SCHEDULER_Task * 1179struct GNUNET_SCHEDULER_Task *
1308GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, 1180GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay,
1309 GNUNET_SCHEDULER_TaskCallback task, 1181 GNUNET_SCHEDULER_TaskCallback task,
1310 void *task_cls) 1182 void *task_cls)
1311{ 1183{
1312 return GNUNET_SCHEDULER_add_delayed_with_priority (delay, 1184 return GNUNET_SCHEDULER_add_delayed_with_priority (delay,
1313 GNUNET_SCHEDULER_PRIORITY_DEFAULT, 1185 GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1314 task, 1186 task,
1315 task_cls); 1187 task_cls);
1316} 1188}
1317 1189
1318 1190
@@ -1333,11 +1205,11 @@ GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay,
1333 */ 1205 */
1334struct GNUNET_SCHEDULER_Task * 1206struct GNUNET_SCHEDULER_Task *
1335GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task, 1207GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task,
1336 void *task_cls) 1208 void *task_cls)
1337{ 1209{
1338 return GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_ZERO, 1210 return GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_ZERO,
1339 task, 1211 task,
1340 task_cls); 1212 task_cls);
1341} 1213}
1342 1214
1343 1215
@@ -1353,7 +1225,7 @@ GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task,
1353 */ 1225 */
1354struct GNUNET_SCHEDULER_Task * 1226struct GNUNET_SCHEDULER_Task *
1355GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task, 1227GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task,
1356 void *task_cls) 1228 void *task_cls)
1357{ 1229{
1358 struct GNUNET_SCHEDULER_Task *t; 1230 struct GNUNET_SCHEDULER_Task *t;
1359 1231
@@ -1370,12 +1242,12 @@ GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task,
1370 t->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; 1242 t->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1371 t->priority = GNUNET_SCHEDULER_PRIORITY_SHUTDOWN; 1243 t->priority = GNUNET_SCHEDULER_PRIORITY_SHUTDOWN;
1372 t->on_shutdown = GNUNET_YES; 1244 t->on_shutdown = GNUNET_YES;
1373 t->lifeness = GNUNET_YES; 1245 t->lifeness = GNUNET_NO;
1374 GNUNET_CONTAINER_DLL_insert (shutdown_head, 1246 GNUNET_CONTAINER_DLL_insert (shutdown_head,
1375 shutdown_tail, 1247 shutdown_tail,
1376 t); 1248 t);
1377 LOG (GNUNET_ERROR_TYPE_DEBUG, 1249 LOG (GNUNET_ERROR_TYPE_DEBUG,
1378 "Adding task: %p\n", 1250 "Adding shutdown task %p\n",
1379 t); 1251 t);
1380 init_backtrace (t); 1252 init_backtrace (t);
1381 return t; 1253 return t;
@@ -1409,6 +1281,33 @@ GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness,
1409} 1281}
1410 1282
1411 1283
1284#if DEBUG_FDS
1285/**
1286 * check a raw file descriptor and abort if it is bad (for debugging purposes)
1287 *
1288 * @param t the task related to the file descriptor
1289 * @param raw_fd the raw file descriptor to check
1290 */
1291void
1292check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1293{
1294 if (-1 != raw_fd)
1295 {
1296 int flags = fcntl (raw_fd, F_GETFD);
1297
1298 if ((flags == -1) && (errno == EBADF))
1299 {
1300 LOG (GNUNET_ERROR_TYPE_ERROR,
1301 "Got invalid file descriptor %d!\n",
1302 raw_fd);
1303 init_backtrace (t);
1304 GNUNET_assert (0);
1305 }
1306 }
1307}
1308#endif
1309
1310
1412/** 1311/**
1413 * Schedule a new task to be run with a specified delay or when any of 1312 * Schedule a new task to be run with a specified delay or when any of
1414 * the specified file descriptor sets is ready. The delay can be used 1313 * the specified file descriptor sets is ready. The delay can be used
@@ -1437,9 +1336,11 @@ GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness,
1437#ifndef MINGW 1336#ifndef MINGW
1438static struct GNUNET_SCHEDULER_Task * 1337static struct GNUNET_SCHEDULER_Task *
1439add_without_sets (struct GNUNET_TIME_Relative delay, 1338add_without_sets (struct GNUNET_TIME_Relative delay,
1440 enum GNUNET_SCHEDULER_Priority priority, 1339 enum GNUNET_SCHEDULER_Priority priority,
1441 int rfd, 1340 const struct GNUNET_NETWORK_Handle *read_nh,
1442 int wfd, 1341 const struct GNUNET_NETWORK_Handle *write_nh,
1342 const struct GNUNET_DISK_FileHandle *read_fh,
1343 const struct GNUNET_DISK_FileHandle *write_fh,
1443 GNUNET_SCHEDULER_TaskCallback task, 1344 GNUNET_SCHEDULER_TaskCallback task,
1444 void *task_cls) 1345 void *task_cls)
1445{ 1346{
@@ -1448,39 +1349,23 @@ add_without_sets (struct GNUNET_TIME_Relative delay,
1448 GNUNET_assert (NULL != active_task); 1349 GNUNET_assert (NULL != active_task);
1449 GNUNET_assert (NULL != task); 1350 GNUNET_assert (NULL != task);
1450 t = GNUNET_new (struct GNUNET_SCHEDULER_Task); 1351 t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1352 init_fd_info (t,
1353 &read_nh,
1354 read_nh ? 1 : 0,
1355 &write_nh,
1356 write_nh ? 1 : 0,
1357 &read_fh,
1358 read_fh ? 1 : 0,
1359 &write_fh,
1360 write_fh ? 1 : 0);
1451 t->callback = task; 1361 t->callback = task;
1452 t->callback_cls = task_cls; 1362 t->callback_cls = task_cls;
1453#if DEBUG_FDS 1363#if DEBUG_FDS
1454 if (-1 != rfd) 1364 check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1455 { 1365 check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1456 int flags = fcntl (rfd, F_GETFD); 1366 check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1457 1367 check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1458 if ((flags == -1) && (errno == EBADF))
1459 {
1460 LOG (GNUNET_ERROR_TYPE_ERROR,
1461 "Got invalid file descriptor %d!\n",
1462 rfd);
1463 init_backtrace (t);
1464 GNUNET_assert (0);
1465 }
1466 }
1467 if (-1 != wfd)
1468 {
1469 int flags = fcntl (wfd, F_GETFD);
1470
1471 if (flags == -1 && errno == EBADF)
1472 {
1473 LOG (GNUNET_ERROR_TYPE_ERROR,
1474 "Got invalid file descriptor %d!\n",
1475 wfd);
1476 init_backtrace (t);
1477 GNUNET_assert (0);
1478 }
1479 }
1480#endif 1368#endif
1481 t->read_fd = rfd;
1482 GNUNET_assert (wfd >= -1);
1483 t->write_fd = wfd;
1484#if PROFILE_DELAYS 1369#if PROFILE_DELAYS
1485 t->start_time = GNUNET_TIME_absolute_get (); 1370 t->start_time = GNUNET_TIME_absolute_get ();
1486#endif 1371#endif
@@ -1490,11 +1375,9 @@ add_without_sets (struct GNUNET_TIME_Relative delay,
1490 GNUNET_CONTAINER_DLL_insert (pending_head, 1375 GNUNET_CONTAINER_DLL_insert (pending_head,
1491 pending_tail, 1376 pending_tail,
1492 t); 1377 t);
1378 driver_add_multiple (t, GNUNET_SCHEDULER_ET_NONE);
1493 max_priority_added = GNUNET_MAX (max_priority_added, 1379 max_priority_added = GNUNET_MAX (max_priority_added,
1494 t->priority); 1380 t->priority);
1495 LOG (GNUNET_ERROR_TYPE_DEBUG,
1496 "Adding task %p\n",
1497 t);
1498 init_backtrace (t); 1381 init_backtrace (t);
1499 return t; 1382 return t;
1500} 1383}
@@ -1507,6 +1390,9 @@ add_without_sets (struct GNUNET_TIME_Relative delay,
1507 * used as a timeout on the socket being ready. The task will be 1390 * used as a timeout on the socket being ready. The task will be
1508 * scheduled for execution once either the delay has expired or the 1391 * scheduled for execution once either the delay has expired or the
1509 * socket operation is ready. It will be run with the DEFAULT priority. 1392 * socket operation is ready. It will be run with the DEFAULT priority.
1393 * Only allowed to be called as long as the scheduler is running
1394 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1395 * called and has not returned yet).
1510 * 1396 *
1511 * @param delay when should this operation time out? 1397 * @param delay when should this operation time out?
1512 * @param rfd read file-descriptor 1398 * @param rfd read file-descriptor
@@ -1522,8 +1408,8 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
1522 void *task_cls) 1408 void *task_cls)
1523{ 1409{
1524 return GNUNET_SCHEDULER_add_read_net_with_priority (delay, 1410 return GNUNET_SCHEDULER_add_read_net_with_priority (delay,
1525 GNUNET_SCHEDULER_PRIORITY_DEFAULT, 1411 GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1526 rfd, task, task_cls); 1412 rfd, task, task_cls);
1527} 1413}
1528 1414
1529 1415
@@ -1534,6 +1420,9 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
1534 * socket being ready. The task will be scheduled for execution once 1420 * socket being ready. The task will be scheduled for execution once
1535 * either the delay has expired or the socket operation is ready. It 1421 * either the delay has expired or the socket operation is ready. It
1536 * will be run with the DEFAULT priority. 1422 * will be run with the DEFAULT priority.
1423 * Only allowed to be called as long as the scheduler is running
1424 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1425 * called and has not returned yet).
1537 * 1426 *
1538 * @param delay when should this operation time out? 1427 * @param delay when should this operation time out?
1539 * @param priority priority to use for the task 1428 * @param priority priority to use for the task
@@ -1545,9 +1434,9 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
1545 */ 1434 */
1546struct GNUNET_SCHEDULER_Task * 1435struct GNUNET_SCHEDULER_Task *
1547GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, 1436GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay,
1548 enum GNUNET_SCHEDULER_Priority priority, 1437 enum GNUNET_SCHEDULER_Priority priority,
1549 struct GNUNET_NETWORK_Handle *rfd, 1438 struct GNUNET_NETWORK_Handle *rfd,
1550 GNUNET_SCHEDULER_TaskCallback task, 1439 GNUNET_SCHEDULER_TaskCallback task,
1551 void *task_cls) 1440 void *task_cls)
1552{ 1441{
1553 return GNUNET_SCHEDULER_add_net_with_priority (delay, priority, 1442 return GNUNET_SCHEDULER_add_net_with_priority (delay, priority,
@@ -1565,6 +1454,9 @@ GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay,
1565 * scheduled for execution once either the delay has expired or the 1454 * scheduled for execution once either the delay has expired or the
1566 * socket operation is ready. It will be run with the priority of 1455 * socket operation is ready. It will be run with the priority of
1567 * the calling task. 1456 * the calling task.
1457 * Only allowed to be called as long as the scheduler is running
1458 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1459 * called and has not returned yet).
1568 * 1460 *
1569 * @param delay when should this operation time out? 1461 * @param delay when should this operation time out?
1570 * @param wfd write file-descriptor 1462 * @param wfd write file-descriptor
@@ -1592,6 +1484,9 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay,
1592 * used as a timeout on the socket being ready. The task will be 1484 * used as a timeout on the socket being ready. The task will be
1593 * scheduled for execution once either the delay has expired or the 1485 * scheduled for execution once either the delay has expired or the
1594 * socket operation is ready. 1486 * socket operation is ready.
1487 * Only allowed to be called as long as the scheduler is running
1488 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1489 * called and has not returned yet).
1595 * 1490 *
1596 * @param delay when should this operation time out? 1491 * @param delay when should this operation time out?
1597 * @param priority priority of the task 1492 * @param priority priority of the task
@@ -1612,6 +1507,9 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay,
1612 GNUNET_SCHEDULER_TaskCallback task, 1507 GNUNET_SCHEDULER_TaskCallback task,
1613 void *task_cls) 1508 void *task_cls)
1614{ 1509{
1510 /* scheduler must be running */
1511 GNUNET_assert (NULL != scheduler_driver);
1512
1615#if MINGW 1513#if MINGW
1616 struct GNUNET_NETWORK_FDSet *s; 1514 struct GNUNET_NETWORK_FDSet *s;
1617 struct GNUNET_SCHEDULER_Task * ret; 1515 struct GNUNET_SCHEDULER_Task * ret;
@@ -1627,10 +1525,13 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay,
1627 GNUNET_NETWORK_fdset_destroy (s); 1525 GNUNET_NETWORK_fdset_destroy (s);
1628 return ret; 1526 return ret;
1629#else 1527#else
1528 GNUNET_assert (on_read || on_write);
1630 GNUNET_assert (GNUNET_NETWORK_get_fd (fd) >= 0); 1529 GNUNET_assert (GNUNET_NETWORK_get_fd (fd) >= 0);
1631 return add_without_sets (delay, priority, 1530 return add_without_sets (delay, priority,
1632 on_read ? GNUNET_NETWORK_get_fd (fd) : -1, 1531 on_read ? fd : NULL,
1633 on_write ? GNUNET_NETWORK_get_fd (fd) : -1, 1532 on_write ? fd : NULL,
1533 NULL,
1534 NULL,
1634 task, task_cls); 1535 task, task_cls);
1635#endif 1536#endif
1636} 1537}
@@ -1642,6 +1543,9 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay,
1642 * used as a timeout on the socket being ready. The task will be 1543 * used as a timeout on the socket being ready. The task will be
1643 * scheduled for execution once either the delay has expired or the 1544 * scheduled for execution once either the delay has expired or the
1644 * socket operation is ready. It will be run with the DEFAULT priority. 1545 * socket operation is ready. It will be run with the DEFAULT priority.
1546 * Only allowed to be called as long as the scheduler is running
1547 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1548 * called and has not returned yet).
1645 * 1549 *
1646 * @param delay when should this operation time out? 1550 * @param delay when should this operation time out?
1647 * @param rfd read file-descriptor 1551 * @param rfd read file-descriptor
@@ -1668,6 +1572,9 @@ GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
1668 * used as a timeout on the socket being ready. The task will be 1572 * used as a timeout on the socket being ready. The task will be
1669 * scheduled for execution once either the delay has expired or the 1573 * scheduled for execution once either the delay has expired or the
1670 * socket operation is ready. It will be run with the DEFAULT priority. 1574 * socket operation is ready. It will be run with the DEFAULT priority.
1575 * Only allowed to be called as long as the scheduler is running
1576 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1577 * called and has not returned yet).
1671 * 1578 *
1672 * @param delay when should this operation time out? 1579 * @param delay when should this operation time out?
1673 * @param wfd write file-descriptor 1580 * @param wfd write file-descriptor
@@ -1694,6 +1601,9 @@ GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay,
1694 * used as a timeout on the socket being ready. The task will be 1601 * used as a timeout on the socket being ready. The task will be
1695 * scheduled for execution once either the delay has expired or the 1602 * scheduled for execution once either the delay has expired or the
1696 * socket operation is ready. 1603 * socket operation is ready.
1604 * Only allowed to be called as long as the scheduler is running
1605 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1606 * called and has not returned yet).
1697 * 1607 *
1698 * @param delay when should this operation time out? 1608 * @param delay when should this operation time out?
1699 * @param priority priority of the task 1609 * @param priority priority of the task
@@ -1712,6 +1622,9 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay,
1712 int on_read, int on_write, 1622 int on_read, int on_write,
1713 GNUNET_SCHEDULER_TaskCallback task, void *task_cls) 1623 GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
1714{ 1624{
1625 /* scheduler must be running */
1626 GNUNET_assert (NULL != scheduler_driver);
1627
1715#if MINGW 1628#if MINGW
1716 struct GNUNET_NETWORK_FDSet *s; 1629 struct GNUNET_NETWORK_FDSet *s;
1717 struct GNUNET_SCHEDULER_Task * ret; 1630 struct GNUNET_SCHEDULER_Task * ret;
@@ -1727,19 +1640,70 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay,
1727 GNUNET_NETWORK_fdset_destroy (s); 1640 GNUNET_NETWORK_fdset_destroy (s);
1728 return ret; 1641 return ret;
1729#else 1642#else
1730 int real_fd; 1643 GNUNET_assert (on_read || on_write);
1731 1644 GNUNET_assert (fd->fd >= 0);
1732 GNUNET_DISK_internal_file_handle_ (fd, &real_fd, sizeof (int)); 1645 return add_without_sets (delay, priority,
1733 GNUNET_assert (real_fd >= 0); 1646 NULL,
1734 return add_without_sets ( 1647 NULL,
1735 delay, priority, 1648 on_read ? fd : NULL,
1736 on_read ? real_fd : -1, 1649 on_write ? fd : NULL,
1737 on_write ? real_fd : -1, 1650 task, task_cls);
1738 task, task_cls);
1739#endif 1651#endif
1740} 1652}
1741 1653
1742 1654
1655void
1656extract_handles (struct GNUNET_SCHEDULER_Task *t,
1657 const struct GNUNET_NETWORK_FDSet *fdset,
1658 const struct GNUNET_NETWORK_Handle ***ntarget,
1659 unsigned int *extracted_nhandles,
1660 const struct GNUNET_DISK_FileHandle ***ftarget,
1661 unsigned int *extracted_fhandles)
1662{
1663 // FIXME: this implementation only works for unix, for WIN32 the file handles
1664 // in fdset must be handled separately
1665 const struct GNUNET_NETWORK_Handle **nhandles;
1666 const struct GNUNET_DISK_FileHandle **fhandles;
1667 unsigned int nhandles_len, fhandles_len;
1668 int sock;
1669
1670 nhandles = NULL;
1671 fhandles = NULL;
1672 nhandles_len = 0;
1673 fhandles_len = 0;
1674 for (sock = 0; sock != fdset->nsds; ++sock)
1675 {
1676 if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1677 {
1678 struct GNUNET_NETWORK_Handle *nhandle;
1679 struct GNUNET_DISK_FileHandle *fhandle;
1680
1681 nhandle = GNUNET_NETWORK_socket_box_native (sock);
1682 if (NULL != nhandle)
1683 {
1684 GNUNET_array_append (nhandles, nhandles_len, nhandle);
1685 }
1686 else
1687 {
1688 fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1689 if (NULL != fhandle)
1690 {
1691 GNUNET_array_append (fhandles, fhandles_len, fhandle);
1692 }
1693 else
1694 {
1695 GNUNET_assert (0);
1696 }
1697 }
1698 }
1699 }
1700 *ntarget = nhandles_len > 0 ? nhandles : NULL;
1701 *ftarget = fhandles_len > 0 ? fhandles : NULL;
1702 *extracted_nhandles = nhandles_len;
1703 *extracted_fhandles = fhandles_len;
1704}
1705
1706
1743/** 1707/**
1744 * Schedule a new task to be run with a specified delay or when any of 1708 * Schedule a new task to be run with a specified delay or when any of
1745 * the specified file descriptor sets is ready. The delay can be used 1709 * the specified file descriptor sets is ready. The delay can be used
@@ -1755,6 +1719,9 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay,
1755 * || any-rs-ready 1719 * || any-rs-ready
1756 * || any-ws-ready) ) 1720 * || any-ws-ready) )
1757 * </code> 1721 * </code>
1722 * Only allowed to be called as long as the scheduler is running
1723 * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
1724 * called and has not returned yet).
1758 * 1725 *
1759 * @param prio how important is this task? 1726 * @param prio how important is this task?
1760 * @param delay how long should we wait? 1727 * @param delay how long should we wait?
@@ -1774,13 +1741,20 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
1774 void *task_cls) 1741 void *task_cls)
1775{ 1742{
1776 struct GNUNET_SCHEDULER_Task *t; 1743 struct GNUNET_SCHEDULER_Task *t;
1777 1744 const struct GNUNET_NETWORK_Handle **read_nhandles;
1778 if ( (NULL == rs) && 1745 const struct GNUNET_NETWORK_Handle **write_nhandles;
1779 (NULL == ws) ) 1746 const struct GNUNET_DISK_FileHandle **read_fhandles;
1747 const struct GNUNET_DISK_FileHandle **write_fhandles;
1748 unsigned int read_nhandles_len, write_nhandles_len,
1749 read_fhandles_len, write_fhandles_len;
1750
1751 if (((NULL == rs) && (NULL == ws)) || ((0 == rs->nsds) && (0 == ws->nsds)))
1780 return GNUNET_SCHEDULER_add_delayed_with_priority (delay, 1752 return GNUNET_SCHEDULER_add_delayed_with_priority (delay,
1781 prio, 1753 prio,
1782 task, 1754 task,
1783 task_cls); 1755 task_cls);
1756 /* scheduler must be running */
1757 GNUNET_assert (NULL != scheduler_driver);
1784 GNUNET_assert (NULL != active_task); 1758 GNUNET_assert (NULL != active_task);
1785 GNUNET_assert (NULL != task); 1759 GNUNET_assert (NULL != task);
1786 t = GNUNET_new (struct GNUNET_SCHEDULER_Task); 1760 t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
@@ -1788,16 +1762,48 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
1788 t->callback_cls = task_cls; 1762 t->callback_cls = task_cls;
1789 t->read_fd = -1; 1763 t->read_fd = -1;
1790 t->write_fd = -1; 1764 t->write_fd = -1;
1765 t->own_handles = GNUNET_YES;
1766 read_nhandles = NULL;
1767 write_nhandles = NULL;
1768 read_fhandles = NULL;
1769 write_fhandles = NULL;
1770 read_nhandles_len = 0;
1771 write_nhandles_len = 0;
1772 read_fhandles_len = 0;
1773 write_fhandles_len = 0;
1791 if (NULL != rs) 1774 if (NULL != rs)
1792 { 1775 {
1793 t->read_set = GNUNET_NETWORK_fdset_create (); 1776 extract_handles (t,
1794 GNUNET_NETWORK_fdset_copy (t->read_set, rs); 1777 rs,
1778 &read_nhandles,
1779 &read_nhandles_len,
1780 &read_fhandles,
1781 &read_fhandles_len);
1795 } 1782 }
1796 if (NULL != ws) 1783 if (NULL != ws)
1797 { 1784 {
1798 t->write_set = GNUNET_NETWORK_fdset_create (); 1785 extract_handles (t,
1799 GNUNET_NETWORK_fdset_copy (t->write_set, ws); 1786 ws,
1787 &write_nhandles,
1788 &write_nhandles_len,
1789 &write_fhandles,
1790 &write_fhandles_len);
1800 } 1791 }
1792 init_fd_info (t,
1793 read_nhandles,
1794 read_nhandles_len,
1795 write_nhandles,
1796 write_nhandles_len,
1797 read_fhandles,
1798 read_fhandles_len,
1799 write_fhandles,
1800 write_fhandles_len);
1801 /* free the arrays of pointers to network / file handles, the actual
1802 * handles will be freed in destroy_task */
1803 GNUNET_array_grow (read_nhandles, read_nhandles_len, 0);
1804 GNUNET_array_grow (write_nhandles, write_nhandles_len, 0);
1805 GNUNET_array_grow (read_fhandles, read_fhandles_len, 0);
1806 GNUNET_array_grow (write_fhandles, write_fhandles_len, 0);
1801#if PROFILE_DELAYS 1807#if PROFILE_DELAYS
1802 t->start_time = GNUNET_TIME_absolute_get (); 1808 t->start_time = GNUNET_TIME_absolute_get ();
1803#endif 1809#endif
@@ -1810,8 +1816,9 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
1810 GNUNET_CONTAINER_DLL_insert (pending_head, 1816 GNUNET_CONTAINER_DLL_insert (pending_head,
1811 pending_tail, 1817 pending_tail,
1812 t); 1818 t);
1819 driver_add_multiple (t, GNUNET_SCHEDULER_ET_NONE);
1813 max_priority_added = GNUNET_MAX (max_priority_added, 1820 max_priority_added = GNUNET_MAX (max_priority_added,
1814 t->priority); 1821 t->priority);
1815 LOG (GNUNET_ERROR_TYPE_DEBUG, 1822 LOG (GNUNET_ERROR_TYPE_DEBUG,
1816 "Adding task %p\n", 1823 "Adding task %p\n",
1817 t); 1824 t);
@@ -1822,17 +1829,18 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
1822 1829
1823/** 1830/**
1824 * Function used by event-loop implementations to signal the scheduler 1831 * Function used by event-loop implementations to signal the scheduler
1825 * that a particular @a task is ready due to an event of type @a et. 1832 * that a particular @a task is ready due to an event specified in the
1833 * et field of @a fdi.
1826 * 1834 *
1827 * This function will then queue the task to notify the application 1835 * This function will then queue the task to notify the application
1828 * that the task is ready (with the respective priority). 1836 * that the task is ready (with the respective priority).
1829 * 1837 *
1830 * @param task the task that is ready, NULL for wake up calls 1838 * @param task the task that is ready
1831 * @param et information about why the task is ready 1839 * @param fdi information about the related FD
1832 */ 1840 */
1833void 1841void
1834GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, 1842GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
1835 enum GNUNET_SCHEDULER_EventType et) 1843 struct GNUNET_SCHEDULER_FdInfo *fdi)
1836{ 1844{
1837 enum GNUNET_SCHEDULER_Reason reason; 1845 enum GNUNET_SCHEDULER_Reason reason;
1838 struct GNUNET_TIME_Absolute now; 1846 struct GNUNET_TIME_Absolute now;
@@ -1842,17 +1850,20 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
1842 if (now.abs_value_us >= task->timeout.abs_value_us) 1850 if (now.abs_value_us >= task->timeout.abs_value_us)
1843 reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; 1851 reason |= GNUNET_SCHEDULER_REASON_TIMEOUT;
1844 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) && 1852 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1845 (0 != (GNUNET_SCHEDULER_ET_IN & et)) ) 1853 (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)) )
1846 reason |= GNUNET_SCHEDULER_REASON_READ_READY; 1854 reason |= GNUNET_SCHEDULER_REASON_READ_READY;
1847 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) && 1855 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1848 (0 != (GNUNET_SCHEDULER_ET_OUT & et)) ) 1856 (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)) )
1849 reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; 1857 reason |= GNUNET_SCHEDULER_REASON_WRITE_READY;
1850 reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; 1858 reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE;
1851 task->reason = reason; 1859 task->reason = reason;
1852 task->fds = &task->fdx; 1860 if (GNUNET_NO == task->in_ready_list)
1853 task->fdx.et = et; 1861 {
1854 task->fds_len = 1; 1862 GNUNET_CONTAINER_DLL_remove (pending_head,
1855 queue_ready_task (task); 1863 pending_tail,
1864 task);
1865 queue_ready_task (task);
1866 }
1856} 1867}
1857 1868
1858 1869
@@ -1862,15 +1873,16 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
1862 * there are tasks left to run just to give other tasks a chance as 1873 * there are tasks left to run just to give other tasks a chance as
1863 * well. If we return #GNUNET_YES, the driver should call this 1874 * well. If we return #GNUNET_YES, the driver should call this
1864 * function again as soon as possible, while if we return #GNUNET_NO 1875 * function again as soon as possible, while if we return #GNUNET_NO
1865 * it must block until the operating system has more work as the 1876 * it must block until either the operating system has more work (the
1866 * scheduler has no more work to do right now. 1877 * scheduler has no more work to do right now) or the timeout set by
1878 * the scheduler (using the set_wakeup callback) is reached.
1867 * 1879 *
1868 * @param sh scheduler handle that was given to the `loop` 1880 * @param sh scheduler handle that was given to the `loop`
1869 * @return #GNUNET_OK if there are more tasks that are ready, 1881 * @return #GNUNET_OK if there are more tasks that are ready,
1870 * and thus we would like to run more (yield to avoid 1882 * and thus we would like to run more (yield to avoid
1871 * blocking other activities for too long) 1883 * blocking other activities for too long)
1872 * #GNUNET_NO if we are done running tasks (yield to block) 1884 * #GNUNET_NO if we are done running tasks (yield to block)
1873 * #GNUNET_SYSERR on error 1885 * #GNUNET_SYSERR on error, e.g. no tasks were ready
1874 */ 1886 */
1875int 1887int
1876GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) 1888GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
@@ -1894,9 +1906,27 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
1894 pending_timeout_last = NULL; 1906 pending_timeout_last = NULL;
1895 queue_ready_task (pos); 1907 queue_ready_task (pos);
1896 } 1908 }
1909 pos = pending_head;
1910 while (NULL != pos)
1911 {
1912 struct GNUNET_SCHEDULER_Task *next = pos->next;
1913 if (now.abs_value_us >= pos->timeout.abs_value_us)
1914 {
1915 pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT;
1916 GNUNET_CONTAINER_DLL_remove (pending_head,
1917 pending_tail,
1918 pos);
1919 queue_ready_task (pos);
1920 }
1921 pos = next;
1922 }
1897 1923
1898 if (0 == ready_count) 1924 if (0 == ready_count)
1899 return GNUNET_NO; 1925 {
1926 LOG (GNUNET_ERROR_TYPE_ERROR,
1927 "GNUNET_SCHEDULER_run_from_driver was called, but no tasks are ready!\n");
1928 return GNUNET_SYSERR;
1929 }
1900 1930
1901 /* find out which task priority level we are going to 1931 /* find out which task priority level we are going to
1902 process this time */ 1932 process this time */
@@ -1916,49 +1946,74 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
1916 while (NULL != (pos = ready_head[p])) 1946 while (NULL != (pos = ready_head[p]))
1917 { 1947 {
1918 GNUNET_CONTAINER_DLL_remove (ready_head[p], 1948 GNUNET_CONTAINER_DLL_remove (ready_head[p],
1919 ready_tail[p], 1949 ready_tail[p],
1920 pos); 1950 pos);
1921 ready_count--; 1951 ready_count--;
1922 current_priority = pos->priority; 1952 current_priority = pos->priority;
1923 current_lifeness = pos->lifeness; 1953 current_lifeness = pos->lifeness;
1924 active_task = pos; 1954 active_task = pos;
1925#if PROFILE_DELAYS 1955#if PROFILE_DELAYS
1926 if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us > 1956 if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
1927 DELAY_THRESHOLD.rel_value_us) 1957 DELAY_THRESHOLD.rel_value_us)
1928 { 1958 {
1929 LOG (GNUNET_ERROR_TYPE_DEBUG, 1959 LOG (GNUNET_ERROR_TYPE_DEBUG,
1930 "Task %p took %s to be scheduled\n", 1960 "Task %p took %s to be scheduled\n",
1931 pos, 1961 pos,
1932 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), 1962 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time),
1933 GNUNET_YES)); 1963 GNUNET_YES));
1934 } 1964 }
1935#endif 1965#endif
1936 tc.reason = pos->reason; 1966 tc.reason = pos->reason;
1937 GNUNET_NETWORK_fdset_zero (sh->rs); 1967 GNUNET_NETWORK_fdset_zero (sh->rs);
1938 GNUNET_NETWORK_fdset_zero (sh->ws); 1968 GNUNET_NETWORK_fdset_zero (sh->ws);
1969 // FIXME: do we have to remove FdInfos from fds if they are not ready?
1939 tc.fds_len = pos->fds_len; 1970 tc.fds_len = pos->fds_len;
1940 tc.fds = pos->fds; 1971 tc.fds = pos->fds;
1941 tc.read_ready = (NULL == pos->read_set) ? sh->rs : pos->read_set; 1972 for (int i = 0; i != pos->fds_len; ++i)
1942 if ( (-1 != pos->read_fd) && 1973 {
1943 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ) 1974 struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
1944 GNUNET_NETWORK_fdset_set_native (sh->rs, 1975 if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
1945 pos->read_fd); 1976 {
1946 tc.write_ready = (NULL == pos->write_set) ? sh->ws : pos->write_set; 1977 GNUNET_NETWORK_fdset_set_native (sh->rs,
1947 if ((-1 != pos->write_fd) && 1978 fdi->sock);
1948 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))) 1979 }
1949 GNUNET_NETWORK_fdset_set_native (sh->ws, 1980 if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
1950 pos->write_fd); 1981 {
1982 GNUNET_NETWORK_fdset_set_native (sh->ws,
1983 fdi->sock);
1984 }
1985 }
1986 tc.read_ready = sh->rs;
1987 tc.write_ready = sh->ws;
1951 LOG (GNUNET_ERROR_TYPE_DEBUG, 1988 LOG (GNUNET_ERROR_TYPE_DEBUG,
1952 "Running task: %p\n", 1989 "Running task %p\n",
1953 pos); 1990 pos);
1991 GNUNET_assert (NULL != pos->callback);
1954 pos->callback (pos->callback_cls); 1992 pos->callback (pos->callback_cls);
1993 if (NULL != pos->fds)
1994 {
1995 int del_result = scheduler_driver->del (scheduler_driver->cls, pos);
1996 if (GNUNET_OK != del_result)
1997 {
1998 LOG (GNUNET_ERROR_TYPE_ERROR,
1999 "driver could not delete task\n");
2000 GNUNET_assert (0);
2001 }
2002 }
1955 active_task = NULL; 2003 active_task = NULL;
1956 dump_backtrace (pos); 2004 dump_backtrace (pos);
1957 destroy_task (pos); 2005 destroy_task (pos);
1958 tasks_run++; 2006 tasks_run++;
1959 } 2007 }
2008 shutdown_if_no_lifeness ();
1960 if (0 == ready_count) 2009 if (0 == ready_count)
2010 {
2011 scheduler_driver->set_wakeup (scheduler_driver->cls,
2012 get_timeout ());
1961 return GNUNET_NO; 2013 return GNUNET_NO;
2014 }
2015 scheduler_driver->set_wakeup (scheduler_driver->cls,
2016 GNUNET_TIME_absolute_get ());
1962 return GNUNET_OK; 2017 return GNUNET_OK;
1963} 2018}
1964 2019
@@ -1981,8 +2036,8 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
1981 */ 2036 */
1982int 2037int
1983GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, 2038GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
1984 GNUNET_SCHEDULER_TaskCallback task, 2039 GNUNET_SCHEDULER_TaskCallback task,
1985 void *task_cls) 2040 void *task_cls)
1986{ 2041{
1987 int ret; 2042 int ret;
1988 struct GNUNET_SIGNAL_Context *shc_int; 2043 struct GNUNET_SIGNAL_Context *shc_int;
@@ -1997,7 +2052,6 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
1997#endif 2052#endif
1998 struct GNUNET_SCHEDULER_Task tsk; 2053 struct GNUNET_SCHEDULER_Task tsk;
1999 const struct GNUNET_DISK_FileHandle *pr; 2054 const struct GNUNET_DISK_FileHandle *pr;
2000 struct GNUNET_SCHEDULER_Handle sh;
2001 2055
2002 /* general set-up */ 2056 /* general set-up */
2003 GNUNET_assert (NULL == active_task); 2057 GNUNET_assert (NULL == active_task);
@@ -2009,54 +2063,56 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
2009 GNUNET_assert (NULL != shutdown_pipe_handle); 2063 GNUNET_assert (NULL != shutdown_pipe_handle);
2010 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, 2064 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
2011 GNUNET_DISK_PIPE_END_READ); 2065 GNUNET_DISK_PIPE_END_READ);
2012 GNUNET_assert (NULL != pr);
2013 my_pid = getpid (); 2066 my_pid = getpid ();
2067 scheduler_driver = driver;
2014 2068
2015 /* install signal handlers */ 2069 /* install signal handlers */
2016 LOG (GNUNET_ERROR_TYPE_DEBUG, 2070 LOG (GNUNET_ERROR_TYPE_DEBUG,
2017 "Registering signal handlers\n"); 2071 "Registering signal handlers\n");
2018 shc_int = GNUNET_SIGNAL_handler_install (SIGINT, 2072 shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
2019 &sighandler_shutdown); 2073 &sighandler_shutdown);
2020 shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, 2074 shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
2021 &sighandler_shutdown); 2075 &sighandler_shutdown);
2022#if (SIGTERM != GNUNET_TERM_SIG) 2076#if (SIGTERM != GNUNET_TERM_SIG)
2023 shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, 2077 shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG,
2024 &sighandler_shutdown); 2078 &sighandler_shutdown);
2025#endif 2079#endif
2026#ifndef MINGW 2080#ifndef MINGW
2027 shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, 2081 shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
2028 &sighandler_pipe); 2082 &sighandler_pipe);
2029 shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, 2083 shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
2030 &sighandler_shutdown); 2084 &sighandler_shutdown);
2031 shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, 2085 shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
2032 &sighandler_shutdown); 2086 &sighandler_shutdown);
2033#endif 2087#endif
2034 2088
2035 /* Setup initial tasks */ 2089 /* Setup initial tasks */
2036 current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; 2090 current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT;
2037 current_lifeness = GNUNET_YES; 2091 current_lifeness = GNUNET_NO;
2038 memset (&tsk, 2092 memset (&tsk,
2039 0, 2093 0,
2040 sizeof (tsk)); 2094 sizeof (tsk));
2041 active_task = &tsk; 2095 active_task = &tsk;
2042 tsk.sh = &sh; 2096 GNUNET_SCHEDULER_add_now (&GNUNET_OS_install_parent_control_handler,
2097 NULL);
2098 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
2099 pr,
2100 &shutdown_cb,
2101 NULL);
2102 current_lifeness = GNUNET_YES;
2043 GNUNET_SCHEDULER_add_with_reason_and_priority (task, 2103 GNUNET_SCHEDULER_add_with_reason_and_priority (task,
2044 task_cls, 2104 task_cls,
2045 GNUNET_SCHEDULER_REASON_STARTUP, 2105 GNUNET_SCHEDULER_REASON_STARTUP,
2046 GNUNET_SCHEDULER_PRIORITY_DEFAULT); 2106 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
2047 GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO,
2048 &GNUNET_OS_install_parent_control_handler,
2049 NULL);
2050 active_task = NULL; 2107 active_task = NULL;
2051 driver->set_wakeup (driver->cls, 2108 scheduler_driver->set_wakeup (scheduler_driver->cls,
2052 GNUNET_TIME_absolute_get ()); 2109 get_timeout ());
2053
2054 /* begin main event loop */ 2110 /* begin main event loop */
2055 sh.rs = GNUNET_NETWORK_fdset_create (); 2111 sh.rs = GNUNET_NETWORK_fdset_create ();
2056 sh.ws = GNUNET_NETWORK_fdset_create (); 2112 sh.ws = GNUNET_NETWORK_fdset_create ();
2057 sh.driver = driver; 2113 GNUNET_NETWORK_fdset_handle_set (sh.rs, pr);
2058 ret = driver->loop (driver->cls, 2114 ret = driver->loop (driver->cls,
2059 &sh); 2115 &sh);
2060 GNUNET_NETWORK_fdset_destroy (sh.rs); 2116 GNUNET_NETWORK_fdset_destroy (sh.rs);
2061 GNUNET_NETWORK_fdset_destroy (sh.ws); 2117 GNUNET_NETWORK_fdset_destroy (sh.ws);
2062 2118
@@ -2073,20 +2129,215 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
2073#endif 2129#endif
2074 GNUNET_DISK_pipe_close (shutdown_pipe_handle); 2130 GNUNET_DISK_pipe_close (shutdown_pipe_handle);
2075 shutdown_pipe_handle = NULL; 2131 shutdown_pipe_handle = NULL;
2132 scheduler_driver = NULL;
2076 return ret; 2133 return ret;
2077} 2134}
2078 2135
2079 2136
2137int
2138select_add (void *cls,
2139 struct GNUNET_SCHEDULER_Task *task,
2140 struct GNUNET_SCHEDULER_FdInfo *fdi)
2141{
2142 struct DriverContext *context = cls;
2143 GNUNET_assert (NULL != context);
2144 GNUNET_assert (NULL != task);
2145 GNUNET_assert (NULL != fdi);
2146 GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
2147 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2148
2149 if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2150 {
2151 /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2152 return GNUNET_SYSERR;
2153 }
2154
2155 struct Scheduled *scheduled = GNUNET_new (struct Scheduled);
2156 scheduled->task = task;
2157 scheduled->fdi = fdi;
2158 scheduled->et = fdi->et;
2159
2160 GNUNET_CONTAINER_DLL_insert (context->scheduled_head,
2161 context->scheduled_tail,
2162 scheduled);
2163 return GNUNET_OK;
2164}
2165
2166
2167int
2168select_del (void *cls,
2169 struct GNUNET_SCHEDULER_Task *task)
2170{
2171 struct DriverContext *context;
2172 struct Scheduled *pos;
2173 int ret;
2174
2175 GNUNET_assert (NULL != cls);
2176
2177 context = cls;
2178 ret = GNUNET_SYSERR;
2179 pos = context->scheduled_head;
2180 while (NULL != pos)
2181 {
2182 struct Scheduled *next = pos->next;
2183 if (pos->task == task)
2184 {
2185 GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
2186 context->scheduled_tail,
2187 pos);
2188 GNUNET_free (pos);
2189 ret = GNUNET_OK;
2190 }
2191 pos = next;
2192 }
2193 return ret;
2194}
2195
2196
2197int
2198select_loop (void *cls,
2199 struct GNUNET_SCHEDULER_Handle *sh)
2200{
2201 struct GNUNET_NETWORK_FDSet *rs;
2202 struct GNUNET_NETWORK_FDSet *ws;
2203 struct DriverContext *context;
2204 int select_result;
2205 int tasks_ready;
2206
2207 context = cls;
2208 GNUNET_assert (NULL != context);
2209 rs = GNUNET_NETWORK_fdset_create ();
2210 ws = GNUNET_NETWORK_fdset_create ();
2211 tasks_ready = GNUNET_NO;
2212 while (NULL != context->scheduled_head ||
2213 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != context->timeout.rel_value_us)
2214 {
2215 LOG (GNUNET_ERROR_TYPE_DEBUG,
2216 "select timeout = %s\n",
2217 GNUNET_STRINGS_relative_time_to_string (context->timeout, GNUNET_NO));
2218
2219 GNUNET_NETWORK_fdset_zero (rs);
2220 GNUNET_NETWORK_fdset_zero (ws);
2221 struct Scheduled *pos;
2222 for (pos = context->scheduled_head; NULL != pos; pos = pos->next)
2223 {
2224 if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2225 {
2226 GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2227 }
2228 if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2229 {
2230 GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2231 }
2232 }
2233 if (NULL == scheduler_select)
2234 {
2235 select_result = GNUNET_NETWORK_socket_select (rs,
2236 ws,
2237 NULL,
2238 context->timeout);
2239 }
2240 else
2241 {
2242 select_result = scheduler_select (scheduler_select_cls,
2243 rs,
2244 ws,
2245 NULL,
2246 context->timeout);
2247 }
2248 if (select_result == GNUNET_SYSERR)
2249 {
2250 if (errno == EINTR)
2251 continue;
2252
2253 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "select");
2254#ifndef MINGW
2255#if USE_LSOF
2256 char lsof[512];
2257
2258 snprintf (lsof, sizeof (lsof), "lsof -p %d", getpid ());
2259 (void) close (1);
2260 (void) dup2 (2, 1);
2261 if (0 != system (lsof))
2262 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
2263 "system");
2264#endif
2265#endif
2266#if DEBUG_FDS
2267 struct Scheduled *s;
2268 for (s = context->scheduled_head; NULL != s; s = s->next)
2269 {
2270 int flags = fcntl (s->fdi->sock, F_GETFD);
2271 if ((flags == -1) && (errno == EBADF))
2272 {
2273 LOG (GNUNET_ERROR_TYPE_ERROR,
2274 "Got invalid file descriptor %d!\n",
2275 s->fdi->sock);
2276 }
2277 }
2278#endif
2279 GNUNET_assert (0);
2280 GNUNET_NETWORK_fdset_destroy (rs);
2281 GNUNET_NETWORK_fdset_destroy (ws);
2282 return GNUNET_SYSERR;
2283 }
2284 for (pos = context->scheduled_head; NULL != pos; pos = pos->next)
2285 {
2286 int is_ready = GNUNET_NO;
2287 if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et) &&
2288 GNUNET_YES == GNUNET_NETWORK_fdset_test_native (rs, pos->fdi->sock))
2289 {
2290 pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2291 is_ready = GNUNET_YES;
2292 }
2293 if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et) &&
2294 GNUNET_YES == GNUNET_NETWORK_fdset_test_native (ws, pos->fdi->sock))
2295 {
2296 pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2297 is_ready = GNUNET_YES;
2298 }
2299 if (GNUNET_YES == is_ready)
2300 {
2301 GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi);
2302 }
2303 }
2304 tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh);
2305 GNUNET_assert (GNUNET_SYSERR != tasks_ready);
2306 }
2307 GNUNET_NETWORK_fdset_destroy (rs);
2308 GNUNET_NETWORK_fdset_destroy (ws);
2309 return GNUNET_OK;
2310}
2311
2312
2313void
2314select_set_wakeup(void *cls,
2315 struct GNUNET_TIME_Absolute dt)
2316{
2317 struct DriverContext *context = cls;
2318 GNUNET_assert (NULL != context);
2319
2320 context->timeout = GNUNET_TIME_absolute_get_remaining (dt);
2321}
2322
2323
2080/** 2324/**
2081 * Obtain the driver for using select() as the event loop. 2325 * Obtain the driver for using select() as the event loop.
2082 * 2326 *
2083 * @return NULL on error 2327 * @return NULL on error
2084 */ 2328 */
2085const struct GNUNET_SCHEDULER_Driver * 2329struct GNUNET_SCHEDULER_Driver *
2086GNUNET_SCHEDULER_driver_select () 2330GNUNET_SCHEDULER_driver_select ()
2087{ 2331{
2088 GNUNET_break (0); // not implemented 2332 struct GNUNET_SCHEDULER_Driver *select_driver;
2089 return NULL; 2333 select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
2334
2335 select_driver->loop = &select_loop;
2336 select_driver->add = &select_add;
2337 select_driver->del = &select_del;
2338 select_driver->set_wakeup = &select_set_wakeup;
2339
2340 return select_driver;
2090} 2341}
2091 2342
2092 2343
diff --git a/src/util/service.c b/src/util/service.c
index fcdf45a51..b4eb33caa 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -1932,6 +1932,11 @@ do_send (void *cls)
1932 size_t left; 1932 size_t left;
1933 const char *buf; 1933 const char *buf;
1934 1934
1935 LOG (GNUNET_ERROR_TYPE_DEBUG,
1936 "service: sending message with type %u",
1937 ntohs(client->msg->type));
1938
1939
1935 client->send_task = NULL; 1940 client->send_task = NULL;
1936 buf = (const char *) client->msg; 1941 buf = (const char *) client->msg;
1937 left = ntohs (client->msg->size) - client->msg_pos; 1942 left = ntohs (client->msg->size) - client->msg_pos;
@@ -1941,6 +1946,8 @@ do_send (void *cls)
1941 GNUNET_assert (ret <= (ssize_t) left); 1946 GNUNET_assert (ret <= (ssize_t) left);
1942 if (0 == ret) 1947 if (0 == ret)
1943 { 1948 {
1949 LOG (GNUNET_ERROR_TYPE_DEBUG,
1950 "no data send");
1944 GNUNET_MQ_inject_error (client->mq, 1951 GNUNET_MQ_inject_error (client->mq,
1945 GNUNET_MQ_ERROR_WRITE); 1952 GNUNET_MQ_ERROR_WRITE);
1946 return; 1953 return;
@@ -1958,6 +1965,9 @@ do_send (void *cls)
1958 if (EPIPE != errno) 1965 if (EPIPE != errno)
1959 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 1966 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1960 "send"); 1967 "send");
1968 LOG (GNUNET_ERROR_TYPE_DEBUG,
1969 "socket send returned with error code %i",
1970 errno);
1961 GNUNET_MQ_inject_error (client->mq, 1971 GNUNET_MQ_inject_error (client->mq,
1962 GNUNET_MQ_ERROR_WRITE); 1972 GNUNET_MQ_ERROR_WRITE);
1963 return; 1973 return;
@@ -2402,7 +2412,7 @@ resume_client_receive (void *cls)
2402 GNUNET_YES); 2412 GNUNET_YES);
2403 if (GNUNET_SYSERR == ret) 2413 if (GNUNET_SYSERR == ret)
2404 { 2414 {
2405 if (NULL != c->drop_task) 2415 if (NULL == c->drop_task)
2406 GNUNET_SERVICE_client_drop (c); 2416 GNUNET_SERVICE_client_drop (c);
2407 return; 2417 return;
2408 } 2418 }
@@ -2431,6 +2441,7 @@ resume_client_receive (void *cls)
2431void 2441void
2432GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c) 2442GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c)
2433{ 2443{
2444 GNUNET_assert (NULL == c->drop_task);
2434 GNUNET_assert (GNUNET_YES == c->needs_continue); 2445 GNUNET_assert (GNUNET_YES == c->needs_continue);
2435 GNUNET_assert (NULL == c->recv_task); 2446 GNUNET_assert (NULL == c->recv_task);
2436 c->needs_continue = GNUNET_NO; 2447 c->needs_continue = GNUNET_NO;
@@ -2513,6 +2524,24 @@ GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c)
2513{ 2524{
2514 struct GNUNET_SERVICE_Handle *sh = c->sh; 2525 struct GNUNET_SERVICE_Handle *sh = c->sh;
2515 2526
2527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2528 "Client dropped: %p (MQ: %p)\n",
2529 c,
2530 c->mq);
2531
2532#if EXECINFO
2533 void *backtrace_array[MAX_TRACE_DEPTH];
2534 int num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH);
2535 char **backtrace_strings =
2536 backtrace_symbols (backtrace_array,
2537 t->num_backtrace_strings);
2538 for (unsigned int i = 0; i < num_backtrace_strings; i++)
2539 LOG (GNUNET_ERROR_TYPE_DEBUG,
2540 "client drop trace %u: %s\n",
2541 i,
2542 backtrace_strings[i]);
2543#endif
2544
2516 if (NULL != c->drop_task) 2545 if (NULL != c->drop_task)
2517 { 2546 {
2518 /* asked to drop twice! */ 2547 /* asked to drop twice! */
diff --git a/src/util/time.c b/src/util/time.c
index 19100ac36..5ffb19ec1 100644
--- a/src/util/time.c
+++ b/src/util/time.c
@@ -693,7 +693,7 @@ GNUNET_TIME_year_to_time (unsigned int year)
693 } 693 }
694 t.tm_year = year - 1900; 694 t.tm_year = year - 1900;
695 t.tm_mday = 1; 695 t.tm_mday = 1;
696 t.tm_mon = 1; 696 t.tm_mon = 0;
697 t.tm_wday = 1; 697 t.tm_wday = 1;
698 t.tm_yday = 1; 698 t.tm_yday = 1;
699 tp = mktime (&t); 699 tp = mktime (&t);