Skip to content

tp: work around clang compiler vectorization bug - #170

Merged
cdamus merged 3 commits into
sokatoafrom
issue/sokatoa-4933-clang21-bug
Jul 31, 2026
Merged

cdamus merged 3 commits into
sokatoafrom
issue/sokatoa-4933-clang21-bug

Conversation

@cdamus

@cdamus cdamus commented Mar 27, 2026

Copy link
Copy Markdown
Collaborator

Apple Clang 21 (macOS 26.4 / Xcode 26) has a vectorization bug that miscompiles the WebSocket unmasking loop in http_server.cc. The pattern mask[i % sizeof(mask)] with a 4-byte mask is compiled into a vector where every other group of 4 bytes is XORed with zero: bytes 0–3 are correctly unmasked, bytes 4–7 stay masked, bytes 8–11 correct,
12–15 masked, etc.

This caused the RPC request field (bytes 4–5 of the inner proto) to be left at its masked value (0x52 instead of 0x10=field-2-varint-tag), which decoded as field_id=10/wire_type=2 instead of field_id=2/varint, making req.request() return 0 (TPM_UNSPECIFIED). The server responded with invalid_request=0.

Also included in this PR is a fix in the Perfetto UI side of the Engine class to fix the application hanging on unexpected results like this from the trace processor shell. So with the broken trace processor that commit 1b1b439 lets the error be shown in the usual way in the Sokatoa Capture Widget instead of it showing a loading spinner forever.

These changes should, of course, work just fine with any other version of the or clang compiler or gcc.


@wpaul-samsung this is the problem I reported initially on your yarn upgrade PR in Sokatoa, which I hadn't realized at the time coincided with an OS/Xcode upgrade on my system.

@colin-grant-work colin-grant-work left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this change, I see the load failure reported; with this change, traces load successfully.

Comment thread ui/src/trace_processor/engine.ts Outdated
Comment on lines +692 to +725
// Reject all pending operations so callers don't hang forever when the
// engine enters a failed state (e.g. after receiving an invalid_request).
for (const p of this.pendingParses) p.reject(error);
this.pendingParses = [];
for (const p of this.pendingEOFs) p.reject(error);
this.pendingEOFs = [];
for (const p of this.pendingResetTraceProcessors) p.reject(error);
this.pendingResetTraceProcessors = [];
for (const p of this.pendingRestoreTables) p.reject(error);
this.pendingRestoreTables = [];
for (const p of this.pendingComputeMetrics) p.reject(error);
this.pendingComputeMetrics = [];
this.pendingReadMetatrace?.reject(error);
this.pendingReadMetatrace = undefined;
this.pendingRegisterSqlPackage?.reject(error);
this.pendingRegisterSqlPackage = undefined;
this.pendingAnalyzeStructuredQueries?.reject(error);
this.pendingAnalyzeStructuredQueries = undefined;
this.pendingTraceSummary?.reject(error);
this.pendingTraceSummary = undefined;
// Complete any pending streaming queries with an error result.
// WritableQueryResult has no reject() method — errors are signalled by
// calling appendResultBatch() with a QueryResult proto that has `error`
// set and a final batch with `is_last_batch=true`.
if (this.pendingQueries.length > 0) {
const errBatch = protos.QueryResult.encode(
protos.QueryResult.create({
error: reason,
batch: [protos.QueryResult.CellsBatch.create({isLastBatch: true})],
}),
).finish();
for (const q of this.pendingQueries) q.appendResultBatch(errBatch);
this.pendingQueries = [];
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking this out into something like a rejectAllPending function would make its goal clear without the opening comment.

cdamus added 3 commits July 31, 2026 14:12
When the trace processor shell returns a protocol error response, the
engine communicating with it just hangs. The engine must accurately
detect the protocol error response and then flush its pending state.
This then lets the error be thrown to Sokatoa for reporting to the user.

Signed-off-by: Christian W. Damus <cdamus@eclipsesource.com>
Apple Clang 21 (macOS 26.4 / Xcode 26) has a vectorization bug that
miscompiles the WebSocket unmasking loop in http_server.cc. The pattern
mask[i % sizeof(mask)] with a 4-byte mask is compiled into a vector
where every other group of 4 bytes is XORed with zero: bytes 0–3 are
correctly unmasked, bytes 4–7 stay masked, bytes 8–11 correct,
12–15 masked, etc.

This caused the RPC request field (bytes 4–5 of the inner proto) to be
left at its masked value (0x52 instead of 0x10=field-2-varint-tag),
which decoded as field_id=10/wire_type=2 instead of field_id=2/varint,
making req.request() return 0 (TPM_UNSPECIFIED). The server responded
with invalid_request=0.

For sarc-acl/sokatoa-internal#4933

Signed-off-by: Christian W. Damus <cdamus@eclipsesource.com>
- extract rejectAllPending function

Signed-off-by: Christian W. Damus <cdamus@eclipsesource.com>
@cdamus
cdamus force-pushed the issue/sokatoa-4933-clang21-bug branch from 9886f46 to 3a56fb8 Compare July 31, 2026 18:17
@cdamus
cdamus merged commit 6e3aca6 into sokatoa Jul 31, 2026
1 check passed
@cdamus
cdamus deleted the issue/sokatoa-4933-clang21-bug branch July 31, 2026 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants