diff options
author | lurchi <lurchi@strangeplace.net> | 2018-01-24 22:52:25 +0100 |
---|---|---|
committer | lurchi <lurchi@strangeplace.net> | 2018-01-24 22:52:25 +0100 |
commit | e7ba3b64baa9aef8f1ca83c6da443cb4a1ec362a (patch) | |
tree | 0be38b7aa6f342eeb92ad10b72f279314cf43af0 /src/util/scheduler.c | |
parent | f0140aa59e7e6570deec0cde35fc0147ee1292cb (diff) | |
download | gnunet-e7ba3b64baa9aef8f1ca83c6da443cb4a1ec362a.tar.gz gnunet-e7ba3b64baa9aef8f1ca83c6da443cb4a1ec362a.zip |
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/scheduler.c')
-rw-r--r-- | src/util/scheduler.c | 47 |
1 files changed, 26 insertions, 21 deletions
diff --git a/src/util/scheduler.c b/src/util/scheduler.c index a8d572a56..2daa6dd80 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c | |||
@@ -1896,11 +1896,10 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, | |||
1896 | * the scheduler (using the set_wakeup callback) is reached. | 1896 | * the scheduler (using the set_wakeup callback) is reached. |
1897 | * | 1897 | * |
1898 | * @param sh scheduler handle that was given to the `loop` | 1898 | * @param sh scheduler handle that was given to the `loop` |
1899 | * @return #GNUNET_OK if there are more tasks that are ready, | 1899 | * @return #GNUNET_YES if there are more tasks that are ready, |
1900 | * and thus we would like to run more (yield to avoid | 1900 | * and thus we would like to run more (yield to avoid |
1901 | * blocking other activities for too long) | 1901 | * blocking other activities for too long) |
1902 | * #GNUNET_NO if we are done running tasks (yield to block) | 1902 | * #GNUNET_NO if we are done running tasks (yield to block) |
1903 | * #GNUNET_SYSERR on error, e.g. no tasks were ready | ||
1904 | */ | 1903 | */ |
1905 | int | 1904 | int |
1906 | GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | 1905 | GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) |
@@ -1944,9 +1943,27 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | |||
1944 | 1943 | ||
1945 | if (0 == ready_count) | 1944 | if (0 == ready_count) |
1946 | { | 1945 | { |
1947 | LOG (GNUNET_ERROR_TYPE_ERROR, | 1946 | struct GNUNET_TIME_Absolute timeout = get_timeout (); |
1948 | "GNUNET_SCHEDULER_run_from_driver was called, but no tasks are ready!\n"); | 1947 | |
1949 | return GNUNET_SYSERR; | 1948 | if (timeout.abs_value_us < now.abs_value_us) |
1949 | { | ||
1950 | /** | ||
1951 | * The driver called this function before the current timeout was | ||
1952 | * reached (and no FD tasks are ready). This can happen in the | ||
1953 | * rare case when the system time is changed while the driver is | ||
1954 | * waiting for the timeout, so we handle this gracefully. It might | ||
1955 | * also be a programming error in the driver though. | ||
1956 | */ | ||
1957 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1958 | "GNUNET_SCHEDULER_run_from_driver did not find any ready " | ||
1959 | "tasks and timeout has not been reached yet."); | ||
1960 | return GNUNET_NO; | ||
1961 | } | ||
1962 | /** | ||
1963 | * the current timeout was reached but no ready tasks were found, | ||
1964 | * internal scheduler error! | ||
1965 | */ | ||
1966 | GNUNET_assert (0); | ||
1950 | } | 1967 | } |
1951 | 1968 | ||
1952 | /* find out which task priority level we are going to | 1969 | /* find out which task priority level we are going to |
@@ -2034,7 +2051,7 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | |||
2034 | } | 2051 | } |
2035 | scheduler_driver->set_wakeup (scheduler_driver->cls, | 2052 | scheduler_driver->set_wakeup (scheduler_driver->cls, |
2036 | GNUNET_TIME_absolute_get ()); | 2053 | GNUNET_TIME_absolute_get ()); |
2037 | return GNUNET_OK; | 2054 | return GNUNET_YES; |
2038 | } | 2055 | } |
2039 | 2056 | ||
2040 | 2057 | ||
@@ -2231,13 +2248,11 @@ select_loop (void *cls, | |||
2231 | struct GNUNET_NETWORK_FDSet *ws; | 2248 | struct GNUNET_NETWORK_FDSet *ws; |
2232 | struct DriverContext *context; | 2249 | struct DriverContext *context; |
2233 | int select_result; | 2250 | int select_result; |
2234 | int tasks_ready; | ||
2235 | 2251 | ||
2236 | context = cls; | 2252 | context = cls; |
2237 | GNUNET_assert (NULL != context); | 2253 | GNUNET_assert (NULL != context); |
2238 | rs = GNUNET_NETWORK_fdset_create (); | 2254 | rs = GNUNET_NETWORK_fdset_create (); |
2239 | ws = GNUNET_NETWORK_fdset_create (); | 2255 | ws = GNUNET_NETWORK_fdset_create (); |
2240 | tasks_ready = GNUNET_NO; | ||
2241 | while (NULL != context->scheduled_head || | 2256 | while (NULL != context->scheduled_head || |
2242 | GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != context->timeout.abs_value_us) | 2257 | GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != context->timeout.abs_value_us) |
2243 | { | 2258 | { |
@@ -2335,21 +2350,11 @@ select_loop (void *cls, | |||
2335 | } | 2350 | } |
2336 | } | 2351 | } |
2337 | } | 2352 | } |
2338 | else | 2353 | if (GNUNET_YES == GNUNET_SCHEDULER_run_from_driver (sh)) |
2339 | { | 2354 | { |
2340 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); | 2355 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2341 | if (now.abs_value_us < context->timeout.abs_value_us) | 2356 | "scheduler has more tasks ready!\n"); |
2342 | { | ||
2343 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2344 | "select was expected to return at %" PRIu64 ", " | ||
2345 | "but returned already at %" PRIu64 "\n", | ||
2346 | context->timeout.abs_value_us, | ||
2347 | now.abs_value_us); | ||
2348 | GNUNET_assert (0); | ||
2349 | } | ||
2350 | } | 2357 | } |
2351 | tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); | ||
2352 | GNUNET_assert (GNUNET_SYSERR != tasks_ready); | ||
2353 | } | 2358 | } |
2354 | GNUNET_NETWORK_fdset_destroy (rs); | 2359 | GNUNET_NETWORK_fdset_destroy (rs); |
2355 | GNUNET_NETWORK_fdset_destroy (ws); | 2360 | GNUNET_NETWORK_fdset_destroy (ws); |