Skip to content

Commit 634295c

Browse files
authored
Merge pull request #73796 from mikeash/fix-resume-function-for-logging
[Concurrency] Refine getResumeFunctionForLogging to avoid reading invalid future contexts.
2 parents 8b55078 + 0f226b6 commit 634295c

File tree

7 files changed

+31
-22
lines changed

7 files changed

+31
-22
lines changed

include/swift/ABI/Task.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,11 @@ class AsyncTask : public Job {
352352
/// failing that will return ResumeTask. The returned function pointer may
353353
/// have a different signature than ResumeTask, and it's only for identifying
354354
/// code associated with the task.
355-
const void *getResumeFunctionForLogging();
355+
///
356+
/// If isStarting is true, look into the resume context when appropriate
357+
/// to pull out a wrapped resume function. If isStarting is false, assume the
358+
/// resume context may not be valid and just return the wrapper.
359+
const void *getResumeFunctionForLogging(bool isStarting);
356360

357361
/// Given that we've already fully established the job context
358362
/// in the current thread, start running this task. To establish

stdlib/public/Concurrency/Task.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ const void
539539
*const swift::_swift_concurrency_debug_task_future_wait_resume_adapter =
540540
reinterpret_cast<void *>(task_future_wait_resume_adapter);
541541

542-
const void *AsyncTask::getResumeFunctionForLogging() {
542+
const void *AsyncTask::getResumeFunctionForLogging(bool isStarting) {
543543
const void *result = reinterpret_cast<const void *>(ResumeTask);
544544

545545
if (ResumeTask == non_future_adapter) {
@@ -553,11 +553,16 @@ const void *AsyncTask::getResumeFunctionForLogging() {
553553
sizeof(FutureAsyncContextPrefix));
554554
result =
555555
reinterpret_cast<const void *>(asyncContextPrefix->asyncEntryPoint);
556-
} else if (ResumeTask == task_wait_throwing_resume_adapter) {
557-
auto context = static_cast<TaskFutureWaitAsyncContext *>(ResumeContext);
558-
result = reinterpret_cast<const void *>(context->ResumeParent);
559-
} else if (ResumeTask == task_future_wait_resume_adapter) {
560-
result = reinterpret_cast<const void *>(ResumeContext->ResumeParent);
556+
}
557+
558+
// Future contexts may not be valid if the task was already running before.
559+
if (isStarting) {
560+
if (ResumeTask == task_wait_throwing_resume_adapter) {
561+
auto context = static_cast<TaskFutureWaitAsyncContext *>(ResumeContext);
562+
result = reinterpret_cast<const void *>(context->ResumeParent);
563+
} else if (ResumeTask == task_future_wait_resume_adapter) {
564+
result = reinterpret_cast<const void *>(ResumeContext->ResumeParent);
565+
}
561566
}
562567

563568
return __ptrauth_swift_runtime_function_entry_strip(result);

stdlib/public/Concurrency/TaskPrivate.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -709,10 +709,10 @@ class alignas(2 * sizeof(void*)) ActiveTaskStatus {
709709
return record_iterator::rangeBeginning(getInnermostRecord());
710710
}
711711

712-
void traceStatusChanged(AsyncTask *task) {
712+
void traceStatusChanged(AsyncTask *task, bool isStarting) {
713713
concurrency::trace::task_status_changed(
714714
task, static_cast<uint8_t>(getStoredPriority()), isCancelled(),
715-
isStoredPriorityEscalated(), isRunning(), isEnqueued());
715+
isStoredPriorityEscalated(), isStarting, isRunning(), isEnqueued());
716716
}
717717
};
718718

@@ -938,7 +938,7 @@ inline void AsyncTask::flagAsRunning() {
938938
if (_private()._status().compare_exchange_weak(oldStatus, newStatus,
939939
/* success */ std::memory_order_relaxed,
940940
/* failure */ std::memory_order_relaxed)) {
941-
newStatus.traceStatusChanged(this);
941+
newStatus.traceStatusChanged(this, true);
942942
adoptTaskVoucher(this);
943943
swift_task_enterThreadLocalContext(
944944
(char *)&_private().ExclusivityAccessSet[0]);

stdlib/public/Concurrency/TaskStatus.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ static bool withStatusRecordLock(AsyncTask *task, ActiveTaskStatus status,
233233

234234
status = newStatus;
235235

236-
status.traceStatusChanged(task);
236+
status.traceStatusChanged(task, false);
237237
worker.flagQueueIsPublished(lockingRecord);
238238
installedLockRecord = true;
239239

@@ -268,7 +268,7 @@ static bool withStatusRecordLock(AsyncTask *task, ActiveTaskStatus status,
268268
if (task->_private()._status().compare_exchange_weak(status, newStatus,
269269
/*success*/ std::memory_order_release,
270270
/*failure*/ std::memory_order_relaxed)) {
271-
newStatus.traceStatusChanged(task);
271+
newStatus.traceStatusChanged(task, false);
272272
break;
273273
}
274274
}
@@ -322,7 +322,7 @@ bool swift::addStatusRecord(AsyncTask *task, TaskStatusRecord *newRecord,
322322
if (task->_private()._status().compare_exchange_weak(oldStatus, newStatus,
323323
/*success*/ std::memory_order_release,
324324
/*failure*/ std::memory_order_relaxed)) {
325-
newStatus.traceStatusChanged(task);
325+
newStatus.traceStatusChanged(task, false);
326326
return true;
327327
} else {
328328
// Retry
@@ -404,7 +404,7 @@ void swift::removeStatusRecord(AsyncTask *task, TaskStatusRecord *record,
404404
if (task->_private()._status().compare_exchange_weak(oldStatus, newStatus,
405405
/*success*/ std::memory_order_relaxed,
406406
/*failure*/ std::memory_order_relaxed)) {
407-
newStatus.traceStatusChanged(task);
407+
newStatus.traceStatusChanged(task, false);
408408
return;
409409
}
410410
}
@@ -436,7 +436,7 @@ void swift::removeStatusRecord(AsyncTask *task, TaskStatusRecord *record,
436436
if (task->_private()._status().compare_exchange_weak(oldStatus, newStatus,
437437
/*success*/ std::memory_order_relaxed,
438438
/*failure*/ std::memory_order_relaxed)) {
439-
newStatus.traceStatusChanged(task);
439+
newStatus.traceStatusChanged(task, false);
440440
return;
441441
}
442442
// Restart the loop again - someone else modified status concurrently
@@ -494,7 +494,7 @@ void swift::removeStatusRecordWhere(
494494
if (task->_private()._status().compare_exchange_weak(oldStatus, newStatus,
495495
/*success*/ std::memory_order_relaxed,
496496
/*failure*/ std::memory_order_relaxed)) {
497-
newStatus.traceStatusChanged(task);
497+
newStatus.traceStatusChanged(task, false);
498498
return;
499499
}
500500
}
@@ -904,7 +904,7 @@ static void swift_task_cancelImpl(AsyncTask *task) {
904904
}
905905
}
906906

907-
newStatus.traceStatusChanged(task);
907+
newStatus.traceStatusChanged(task, false);
908908
if (newStatus.getInnermostRecord() == NULL) {
909909
// No records, nothing to propagate
910910
return;

stdlib/public/Concurrency/Tracing.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ void task_create(AsyncTask *task, AsyncTask *parent, TaskGroup *group,
6464
void task_destroy(AsyncTask *task);
6565

6666
void task_status_changed(AsyncTask *task, uint8_t maxPriority, bool isCancelled,
67-
bool isEscalated, bool isRunning, bool isEnqueued);
67+
bool isEscalated, bool isStarting, bool isRunning, bool isEnqueued);
6868

6969
void task_flags_changed(AsyncTask *task, uint8_t jobPriority, bool isChildTask,
7070
bool isFuture, bool isGroupChildTask,

stdlib/public/Concurrency/TracingSignpost.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ inline void task_create(AsyncTask *task, AsyncTask *parent, TaskGroup *group,
193193
" resumefn=%p jobPriority=%u isChildTask=%{bool}d, isFuture=%{bool}d "
194194
"isGroupChildTask=%{bool}d isAsyncLetTask=%{bool}d parent=%" PRIx64
195195
" group=%p asyncLet=%p",
196-
task->getTaskId(), task->getResumeFunctionForLogging(), jobPriority,
196+
task->getTaskId(), task->getResumeFunctionForLogging(true), jobPriority,
197197
isChildTask, isFuture, isGroupChildTask, isAsyncLetTask, parentID, group,
198198
asyncLet);
199199
}
@@ -207,15 +207,15 @@ inline void task_destroy(AsyncTask *task) {
207207

208208
inline void task_status_changed(AsyncTask *task, uint8_t maxPriority,
209209
bool isCancelled, bool isEscalated,
210-
bool isRunning, bool isEnqueued) {
210+
bool isStarting, bool isRunning, bool isEnqueued) {
211211
ENSURE_LOGS();
212212
auto id = os_signpost_id_make_with_pointer(TaskLog, task);
213213
os_signpost_event_emit(
214214
TaskLog, id, SWIFT_LOG_TASK_STATUS_CHANGED_NAME,
215215
"task=%" PRIx64 " resumefn=%p "
216216
"maxPriority=%u, isCancelled=%{bool}d "
217217
"isEscalated=%{bool}d, isRunning=%{bool}d, isEnqueued=%{bool}d",
218-
task->getTaskId(), task->getResumeFunctionForLogging(), maxPriority,
218+
task->getTaskId(), task->getResumeFunctionForLogging(isStarting), maxPriority,
219219
isCancelled, isEscalated, isRunning, isEnqueued);
220220
}
221221

stdlib/public/Concurrency/TracingStubs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ inline void task_resume(AsyncTask *task) {}
5656

5757
inline void task_status_changed(AsyncTask *task, uint8_t maxPriority,
5858
bool isCancelled, bool isEscalated,
59-
bool isRunning, bool isEnqueued) {}
59+
bool isStarting, bool isRunning, bool isEnqueued) {}
6060

6161
inline void task_flags_changed(AsyncTask *task, uint8_t jobPriority,
6262
bool isChildTask, bool isFuture,

0 commit comments

Comments
 (0)