Skip to content

Fix asyncMainDrainQueue noreturn warning #61692

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions include/swift/Runtime/Concurrency.h
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,19 @@ SWIFT_EXPORT_FROM(swift_Concurrency)
SWIFT_CC(swift) void (*swift_task_enqueueMainExecutor_hook)(
Job *job, swift_task_enqueueMainExecutor_original original);

/// A hook to override the entrypoint to the main runloop used to drive the
/// concurrency runtime and drain the main queue. This function must not return.
/// Note: If the hook is wrapping the original function and the `compatOverride`
/// is passed in, the `original` function pointer must be passed into the
/// compatibility override function as the original function.
typedef SWIFT_CC(swift) void (*swift_task_asyncMainDrainQueue_original)();
typedef SWIFT_CC(swift) void (*swift_task_asyncMainDrainQueue_override)(
swift_task_asyncMainDrainQueue_original original);
SWIFT_EXPORT_FROM(swift_Concurrency)
SWIFT_CC(swift) void (*swift_task_asyncMainDrainQueue_hook)(
swift_task_asyncMainDrainQueue_original original,
swift_task_asyncMainDrainQueue_override compatOverride);

/// Initialize the runtime storage for a default actor.
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
void swift_defaultActor_initialize(DefaultActor *actor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ static OverrideSection *getOverrideSectionPtr() {
return nullptr; \
return Section->name; \
}

#define OVERRIDE_NORETURN(name, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
Override_ ## name swift::getOverride_ ## name() { \
auto *Section = getOverrideSectionPtr(); \
if (Section == nullptr) \
nullptr; \
Section->name; \
}

#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH

#endif // #ifdef SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@
# define OVERRIDE_TASK_GROUP OVERRIDE
# define OVERRIDE_TASK_LOCAL OVERRIDE
# define OVERRIDE_TASK_STATUS OVERRIDE
#ifndef HOOKED_OVERRIDE_TASK_NORETURN
# define HOOKED_OVERRIDE_TASK_NORETURN(name, attrs, ccAttrs, namespace, \
typedArgs, namedArgs) \
OVERRIDE(name, void, attrs, ccAttrs, namespace, typedArgs, namedArgs)
#endif
#else
# ifndef OVERRIDE_ACTOR
# define OVERRIDE_ACTOR(...)
Expand All @@ -96,6 +101,9 @@
# ifndef OVERRIDE_TASK_STATUS
# define OVERRIDE_TASK_STATUS(...)
# endif
# ifndef HOOKED_OVERRIDE_TASK_NORETURN
# define HOOKED_OVERRIDE_TASK_NORETURN(...)
# endif
#endif

OVERRIDE_ACTOR(task_enqueue, void,
Expand Down Expand Up @@ -181,9 +189,10 @@ OVERRIDE_TASK(task_createNullaryContinuationJob, NullaryContinuationJob *,
(size_t priority,
AsyncTask *continuation), (priority, continuation))

OVERRIDE_TASK(task_asyncMainDrainQueue, void,
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::,
, )
HOOKED_OVERRIDE_TASK_NORETURN(task_asyncMainDrainQueue,
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
swift::, ,)


OVERRIDE_TASK(task_suspend, AsyncTask *,
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
Expand Down Expand Up @@ -380,3 +389,4 @@ OVERRIDE_TASK_STATUS(task_escalate, JobPriority,
#undef OVERRIDE_TASK_GROUP
#undef OVERRIDE_TASK_LOCAL
#undef OVERRIDE_TASK_STATUS
#undef HOOKED_OVERRIDE_TASK_NORETURN
44 changes: 44 additions & 0 deletions stdlib/public/Concurrency/Task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1589,5 +1589,49 @@ static void swift_task_asyncMainDrainQueueImpl() {
#endif
}

SWIFT_CC(swift)
void (*swift::swift_task_asyncMainDrainQueue_hook)(
swift_task_asyncMainDrainQueue_original original,
swift_task_asyncMainDrainQueue_override compatOverride) = nullptr;

#define OVERRIDE_TASK COMPATIBILITY_OVERRIDE

#ifdef SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT
/// The original COMPATIBILITY_OVERRIDE defined in CompatibilityOverride.h
/// returns the result of the impl function and override function. This results
/// in a warning emitted for noreturn functions. Overriding the override macro
/// to not return.
#define HOOKED_OVERRIDE_TASK_NORETURN(name, attrs, ccAttrs, namespace, \
typedArgs, namedArgs) \
attrs ccAttrs void namespace swift_##name COMPATIBILITY_PAREN(typedArgs) { \
static Override_##name Override; \
static swift_once_t Predicate; \
swift_once( \
&Predicate, [](void *) { Override = getOverride_##name(); }, nullptr); \
if (swift_##name##_hook) { \
swift_##name##_hook(COMPATIBILITY_UNPAREN_WITH_COMMA(namedArgs) \
swift_##name##Impl, \
Override); \
abort(); \
} \
if (Override != nullptr) \
Override(COMPATIBILITY_UNPAREN_WITH_COMMA(namedArgs) \
swift_##name##Impl); \
swift_##name##Impl COMPATIBILITY_PAREN(namedArgs); \
}

#else // ifndef SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT
// Call directly through to the original implementation when we don't support
// overrides.
#define HOOKED_OVERRIDE_TASK_NORETURN(name, attrs, ccAttrs, namespace, \
typedArgs, namedArgs) \
attrs ccAttrs void namespace swift_##name COMPATIBILITY_PAREN(typedArgs) { \
if (swift_##name##_hook) { \
swift_##name##_hook(swift_##name##Impl, nullptr); \
abort(); \
} \
swift_##name##Impl COMPATIBILITY_PAREN(namedArgs); \
}
#endif // #else SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT

#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH
52 changes: 52 additions & 0 deletions unittests/runtime/CompatibilityOverrideConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
#include "swift/Runtime/Concurrency.h"
#include "gtest/gtest.h"

#if __has_include("pthread.h")

#define RUN_ASYNC_MAIN_DRAIN_QUEUE_TEST 1
#include <pthread.h>
#endif // HAVE_PTHREAD_H

#include <stdio.h>

using namespace swift;
Expand All @@ -44,6 +50,15 @@ ExecutorRef getEmptyValue() {
Ran = true; \
return getEmptyValue<ret>(); \
}
#define OVERRIDE_TASK_NORETURN(name, attrs, ccAttrs, namespace, typedArgs, \
namedArgs) \
static ccAttrs void name##Override(COMPATIBILITY_UNPAREN_WITH_COMMA( \
typedArgs) Original_##name originalImpl) { \
if (!EnableOverride) \
originalImpl COMPATIBILITY_PAREN(namedArgs); \
Ran = true; \
}

#include "../../stdlib/public/CompatibilityOverride/CompatibilityOverrideConcurrency.def"

struct OverrideSection {
Expand Down Expand Up @@ -82,6 +97,16 @@ static void swift_task_enqueueMainExecutor_override(
Ran = true;
}

#ifdef RUN_ASYNC_MAIN_DRAIN_QUEUE_TEST
[[noreturn]] SWIFT_CC(swift)
static void swift_task_asyncMainDrainQueue_override_fn(
swift_task_asyncMainDrainQueue_original original,
swift_task_asyncMainDrainQueue_override compatOverride) {
Ran = true;
pthread_exit(nullptr); // noreturn function
}
#endif

class CompatibilityOverrideConcurrencyTest : public ::testing::Test {
protected:
virtual void SetUp() {
Expand All @@ -100,6 +125,10 @@ class CompatibilityOverrideConcurrencyTest : public ::testing::Test {
swift_task_enqueueGlobalWithDelay_override;
swift_task_enqueueMainExecutor_hook =
swift_task_enqueueMainExecutor_override;
#ifdef RUN_ASYNC_MAIN_DRAIN_QUEUE_TEST
swift_task_asyncMainDrainQueue_hook =
swift_task_asyncMainDrainQueue_override_fn;
#endif
}

virtual void TearDown() {
Expand Down Expand Up @@ -255,4 +284,27 @@ TEST_F(CompatibilityOverrideConcurrencyTest, test_swift_task_escalate) {
swift_task_escalate(nullptr, {});
}

#if RUN_ASYNC_MAIN_DRAIN_QUEUE_TEST
TEST_F(CompatibilityOverrideConcurrencyTest, test_swift_task_asyncMainDrainQueue) {

auto runner = [](void *) -> void * {
swift_task_asyncMainDrainQueue();
return nullptr;
};

int ret = 0;
pthread_t thread;
pthread_attr_t attrs;
ret = pthread_attr_init(&attrs);
ASSERT_EQ(ret, 0);
ret = pthread_create(&thread, &attrs, runner, nullptr);
ASSERT_EQ(ret, 0);
void * result = nullptr;
ret = pthread_join(thread, &result);
ASSERT_EQ(ret, 0);
pthread_attr_destroy(&attrs);
ASSERT_EQ(ret, 0);
}
#endif

#endif