diff --git a/src/lib/core/fiber.c b/src/lib/core/fiber.c index fab7740b23f28d3199f1ecddb458e710b10108c8..f8b85d99de317a36c9e7a288bfcb6feb12468c94 100644 --- a/src/lib/core/fiber.c +++ b/src/lib/core/fiber.c @@ -608,10 +608,18 @@ fiber_reschedule(void) int fiber_join(struct fiber *fiber) +{ + int rc = fiber_join_timeout(fiber, TIMEOUT_INFINITY); + return rc; +} + +int +fiber_join_timeout(struct fiber *fiber, double timeout) { assert(fiber->flags & FIBER_IS_JOINABLE); if (! fiber_is_dead(fiber)) { + bool exceeded = false; do { /* * In case fiber is cancelled during yield @@ -620,8 +628,27 @@ fiber_join(struct fiber *fiber) * to put it back in. */ rlist_add_tail_entry(&fiber->wake, fiber(), state); - fiber_yield(); - } while (! fiber_is_dead(fiber)); + if (timeout != TIMEOUT_INFINITY) { + double time = fiber_clock(); + exceeded = fiber_yield_timeout(timeout); + timeout -= (fiber_clock() - time); + } else { + fiber_yield(); + } + } while (! fiber_is_dead(fiber) && ! exceeded && timeout > 0); + } + + if (! fiber_is_dead(fiber)) { + /* + * Not exactly the right error message for this place. Error + * message is generated based on the ETIMEDOUT code, that is + * used for network timeouts in linux. But in other places, + * this type of error is always used when the timeout expires, + * regardless of whether it is related to the network (see + * cbus_call for example). + */ + diag_set(TimedOut); + return -1; } /* Move exception to the caller */ diff --git a/src/lib/core/fiber.h b/src/lib/core/fiber.h index 386c3bd22f5c7e01b53357335eaee60654a2144d..b9eeef69760244d3d9bc7ff3888e6388bc91cd3e 100644 --- a/src/lib/core/fiber.h +++ b/src/lib/core/fiber.h @@ -328,6 +328,22 @@ fiber_set_joinable(struct fiber *fiber, bool yesno); API_EXPORT int fiber_join(struct fiber *f); +/** + * Wait until the fiber is dead or timeout exceeded. + * In case timeout == TIMEOUT_INFINITY, this function + * same as fiber_join function. + * Return fiber execution status to the caller or -1 + * if timeout exceeded and set diag. + * The fiber must not be detached (@sa fiber_set_joinable()). + * @pre FIBER_IS_JOINABLE flag is set. + * + * \param f fiber to be woken up + * \param timeout time during which we wait for the fiber completion + * \return fiber function ret code or -1 in case if timeout exceeded + */ +API_EXPORT int +fiber_join_timeout(struct fiber *f, double timeout); + /** * Put the current fiber to sleep for at least 's' seconds. *