Skip to content

Commit 3283f1e

Browse files
committed
[exclusivity] Add logging lock/flushing to prevent output interleaving.
(cherry picked from commit e662a14)
1 parent 8429d0d commit 3283f1e

File tree

1 file changed

+75
-27
lines changed

1 file changed

+75
-27
lines changed

stdlib/public/runtime/Exclusivity.cpp

Lines changed: 75 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
// NOTE: This should really be applied in the CMakeLists.txt. However, we do
1818
// not have a way to currently specify that at the target specific level yet.
19+
1920
#if defined(_WIN32)
2021
#define NOMINMAX
2122
#define WIN32_LEAN_AND_MEAN
@@ -65,6 +66,39 @@ static inline bool isExclusivityLoggingEnabled() {
6566
return runtime::environment::SWIFT_DEBUG_RUNTIME_EXCLUSIVITY_LOGGING();
6667
}
6768

69+
static inline void _flockfile_stderr() {
70+
#if defined(_WIN32)
71+
_lock_file(stderr);
72+
#elif defined(__wasi__)
73+
// WebAssembly/WASI doesn't support file locking yet
74+
// https://bugs.swift.org/browse/SR-12097
75+
#else
76+
flockfile(stderr);
77+
#endif
78+
}
79+
80+
static inline void _funlockfile_stderr() {
81+
#if defined(_WIN32)
82+
_unlock_file(stderr);
83+
#elif defined(__wasi__)
84+
// WebAssembly/WASI doesn't support file locking yet
85+
// https://bugs.swift.org/browse/SR-12097
86+
#else
87+
funlockfile(stderr);
88+
#endif
89+
}
90+
91+
/// Used to ensure that logging printfs are deterministic.
92+
static inline void withLoggingLock(std::function<void()> func) {
93+
assert(isExclusivityLoggingEnabled() &&
94+
"Should only be called if exclusivity logging is enabled!");
95+
96+
_flockfile_stderr();
97+
func();
98+
fflush(stderr);
99+
_funlockfile_stderr();
100+
}
101+
68102
#endif
69103

70104
SWIFT_ALWAYS_INLINE
@@ -191,8 +225,10 @@ class AccessSet {
191225

192226
bool insert(Access *access, void *pc, void *pointer, ExclusivityFlags flags) {
193227
#ifndef NDEBUG
194-
if (isExclusivityLoggingEnabled())
195-
fprintf(stderr, "Inserting new access: %p\n", access);
228+
if (isExclusivityLoggingEnabled()) {
229+
withLoggingLock(
230+
[&]() { fprintf(stderr, "Inserting new access: %p\n", access); });
231+
}
196232
#endif
197233
auto action = getAccessAction(flags);
198234

@@ -216,7 +252,7 @@ class AccessSet {
216252
if (!isTracking(flags)) {
217253
#ifndef NDEBUG
218254
if (isExclusivityLoggingEnabled()) {
219-
fprintf(stderr, " Not tracking!\n");
255+
withLoggingLock([&]() { fprintf(stderr, " Not tracking!\n"); });
220256
}
221257
#endif
222258
return false;
@@ -227,8 +263,10 @@ class AccessSet {
227263
Head = access;
228264
#ifndef NDEBUG
229265
if (isExclusivityLoggingEnabled()) {
230-
fprintf(stderr, " Tracking!\n");
231-
swift_dumpTrackedAccesses();
266+
withLoggingLock([&]() {
267+
fprintf(stderr, " Tracking!\n");
268+
swift_dumpTrackedAccesses();
269+
});
232270
}
233271
#endif
234272
return true;
@@ -237,8 +275,10 @@ class AccessSet {
237275
void remove(Access *access) {
238276
assert(Head && "removal from empty AccessSet");
239277
#ifndef NDEBUG
240-
if (isExclusivityLoggingEnabled())
241-
fprintf(stderr, "Removing access: %p\n", access);
278+
if (isExclusivityLoggingEnabled()) {
279+
withLoggingLock(
280+
[&]() { fprintf(stderr, "Removing access: %p\n", access); });
281+
}
242282
#endif
243283
auto cur = Head;
244284
// Fast path: stack discipline.
@@ -708,20 +748,24 @@ void swift::swift_task_enterThreadLocalContext(char *state) {
708748

709749
#ifndef NDEBUG
710750
if (isExclusivityLoggingEnabled()) {
711-
fprintf(stderr,
712-
"Entering Thread Local Context. Before Swizzle. Task: %p\n",
713-
taskCtx.getTaskAddress());
714-
taskCtx.dump();
715-
swift_dumpTrackedAccesses();
716-
}
717-
718-
auto logEndState = [&] {
719-
if (isExclusivityLoggingEnabled()) {
751+
withLoggingLock([&]() {
720752
fprintf(stderr,
721-
"Entering Thread Local Context. After Swizzle. Task: %p\n",
753+
"Entering Thread Local Context. Before Swizzle. Task: %p\n",
722754
taskCtx.getTaskAddress());
723755
taskCtx.dump();
724756
swift_dumpTrackedAccesses();
757+
});
758+
}
759+
760+
auto logEndState = [&] {
761+
if (isExclusivityLoggingEnabled()) {
762+
withLoggingLock([&]() {
763+
fprintf(stderr,
764+
"Entering Thread Local Context. After Swizzle. Task: %p\n",
765+
taskCtx.getTaskAddress());
766+
taskCtx.dump();
767+
swift_dumpTrackedAccesses();
768+
});
725769
}
726770
};
727771
#else
@@ -794,20 +838,24 @@ void swift::swift_task_exitThreadLocalContext(char *state) {
794838

795839
#ifndef NDEBUG
796840
if (isExclusivityLoggingEnabled()) {
797-
fprintf(stderr,
798-
"Exiting Thread Local Context. Before Swizzle. Task: %p\n",
799-
taskCtx.getTaskAddress());
800-
taskCtx.dump();
801-
swift_dumpTrackedAccesses();
802-
}
803-
804-
auto logEndState = [&] {
805-
if (isExclusivityLoggingEnabled()) {
841+
withLoggingLock([&]() {
806842
fprintf(stderr,
807-
"Exiting Thread Local Context. After Swizzle. Task: %p\n",
843+
"Exiting Thread Local Context. Before Swizzle. Task: %p\n",
808844
taskCtx.getTaskAddress());
809845
taskCtx.dump();
810846
swift_dumpTrackedAccesses();
847+
});
848+
}
849+
850+
auto logEndState = [&] {
851+
if (isExclusivityLoggingEnabled()) {
852+
withLoggingLock([&]() {
853+
fprintf(stderr,
854+
"Exiting Thread Local Context. After Swizzle. Task: %p\n",
855+
taskCtx.getTaskAddress());
856+
taskCtx.dump();
857+
swift_dumpTrackedAccesses();
858+
});
811859
}
812860
};
813861
#else

0 commit comments

Comments
 (0)