Skip to content

Commit 3068891

Browse files
committed
orchestrator: lock the saturation flag set from worker threads
ORCH_SAT_COMPONENT_LINES_DROPPED was OR'd into orchestrator_saturation from the per-thread component read path without the result mutex, while the other writers hold it — a non-atomic read-modify-write racing across worker threads (a set bit could be lost). C99 cross builds rule out _Atomic, so collect a local flag during the lock-free per-thread clog allocation and set the shared flag once under RESULT_LOCK.
1 parent 509c5b2 commit 3068891

1 file changed

Lines changed: 11 additions & 3 deletions

File tree

src/orchestrator.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,8 +1212,11 @@ static int handle_component_line(struct component_log *clog,
12121212
* grown geometrically — no fixed cap, so noisy components do not silently
12131213
* lose their tail. Non-verbose runs never enter this branch and never
12141214
* allocate. Allocation failures degrade gracefully: the line is dropped (and
1215-
* counts as truncated), but capture continues for subsequent lines. */
1215+
* counts as truncated), but capture continues for subsequent lines. clog is
1216+
* per-thread, so its realloc/malloc need no lock; only the shared saturation
1217+
* flag does (this runs from any worker thread). */
12161218
if (clog && verbose) {
1219+
int dropped = 0;
12171220
if (clog->num_lines >= clog->lines_cap) {
12181221
int new_cap =
12191222
clog->lines_cap ? clog->lines_cap * 2 : COMPONENT_LINES_INITIAL_CAP;
@@ -1222,7 +1225,7 @@ static int handle_component_line(struct component_log *clog,
12221225
clog->lines = bigger;
12231226
clog->lines_cap = new_cap;
12241227
} else {
1225-
orchestrator_saturation |= ORCH_SAT_COMPONENT_LINES_DROPPED;
1228+
dropped = 1;
12261229
}
12271230
}
12281231
if (clog->num_lines < clog->lines_cap) {
@@ -1231,9 +1234,14 @@ static int handle_component_line(struct component_log *clog,
12311234
snprintf(copy, MAX_LINE_LEN, "%s", line);
12321235
clog->lines[clog->num_lines++] = copy;
12331236
} else {
1234-
orchestrator_saturation |= ORCH_SAT_COMPONENT_LINES_DROPPED;
1237+
dropped = 1;
12351238
}
12361239
}
1240+
if (dropped) {
1241+
RESULT_LOCK();
1242+
orchestrator_saturation |= ORCH_SAT_COMPONENT_LINES_DROPPED;
1243+
RESULT_UNLOCK();
1244+
}
12371245
}
12381246

12391247
/* Origin (provenance) is the component name — captured at the orchestrator

0 commit comments

Comments
 (0)