aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorlurchi <lurchi@strangeplace.net>2018-01-24 22:52:25 +0100
committerlurchi <lurchi@strangeplace.net>2018-01-24 22:52:25 +0100
commite7ba3b64baa9aef8f1ca83c6da443cb4a1ec362a (patch)
tree0be38b7aa6f342eeb92ad10b72f279314cf43af0 /src/util
parentf0140aa59e7e6570deec0cde35fc0147ee1292cb (diff)
make GNUNET_SCHEDULER_run_from_driver more graceful
GNUNET_SCHEDULER_run_from_driver may now be called without any tasks being ready if the timeout has not been reached yet. A warning is printed because it may be a programming error in the driver (see comments)
Diffstat (limited to 'src/util')
-rw-r--r--src/util/scheduler.c47
1 files changed, 26 insertions, 21 deletions
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index a8d572a56f..2daa6dd80f 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -1896,11 +1896,10 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
* the scheduler (using the set_wakeup callback) is reached.
*
* @param sh scheduler handle that was given to the `loop`
- * @return #GNUNET_OK if there are more tasks that are ready,
+ * @return #GNUNET_YES if there are more tasks that are ready,
* and thus we would like to run more (yield to avoid
* blocking other activities for too long)
* #GNUNET_NO if we are done running tasks (yield to block)
- * #GNUNET_SYSERR on error, e.g. no tasks were ready
*/
int
GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
@@ -1944,9 +1943,27 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
if (0 == ready_count)
{
- LOG (GNUNET_ERROR_TYPE_ERROR,
- "GNUNET_SCHEDULER_run_from_driver was called, but no tasks are ready!\n");
- return GNUNET_SYSERR;
+ struct GNUNET_TIME_Absolute timeout = get_timeout ();
+
+ if (timeout.abs_value_us < now.abs_value_us)
+ {
+ /**
+ * The driver called this function before the current timeout was
+ * reached (and no FD tasks are ready). This can happen in the
+ * rare case when the system time is changed while the driver is
+ * waiting for the timeout, so we handle this gracefully. It might
+ * also be a programming error in the driver though.
+ */
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "GNUNET_SCHEDULER_run_from_driver did not find any ready "
+ "tasks and timeout has not been reached yet.");
+ return GNUNET_NO;
+ }
+ /**
+ * the current timeout was reached but no ready tasks were found,
+ * internal scheduler error!
+ */
+ GNUNET_assert (0);
}
/* find out which task priority level we are going to
@@ -2034,7 +2051,7 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
}
scheduler_driver->set_wakeup (scheduler_driver->cls,
GNUNET_TIME_absolute_get ());
- return GNUNET_OK;
+ return GNUNET_YES;
}
@@ -2231,13 +2248,11 @@ select_loop (void *cls,
struct GNUNET_NETWORK_FDSet *ws;
struct DriverContext *context;
int select_result;
- int tasks_ready;
context = cls;
GNUNET_assert (NULL != context);
rs = GNUNET_NETWORK_fdset_create ();
ws = GNUNET_NETWORK_fdset_create ();
- tasks_ready = GNUNET_NO;
while (NULL != context->scheduled_head ||
GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != context->timeout.abs_value_us)
{
@@ -2335,21 +2350,11 @@ select_loop (void *cls,
}
}
}
- else
+ if (GNUNET_YES == GNUNET_SCHEDULER_run_from_driver (sh))
{
- struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
- if (now.abs_value_us < context->timeout.abs_value_us)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "select was expected to return at %" PRIu64 ", "
- "but returned already at %" PRIu64 "\n",
- context->timeout.abs_value_us,
- now.abs_value_us);
- GNUNET_assert (0);
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "scheduler has more tasks ready!\n");
}
- tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh);
- GNUNET_assert (GNUNET_SYSERR != tasks_ready);
}
GNUNET_NETWORK_fdset_destroy (rs);
GNUNET_NETWORK_fdset_destroy (ws);