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.
  *