Skip to content

Commit db1a7d4

Browse files
devongovettthecrypticace
authored andcommitted
Fix segmentation fault when loading @tailwindcss/oxide in a Worker thread (#17276)
When Tailwind is loaded in a Node Worker thread, it currently causes a segmentation fault on Linux when the thread exits. This is due to a longstanding issue in Rust that affects all native modules: rust-lang/rust#91979. I reported this years ago but unfortunately it is still not fixed, and seems to have gotten worse in Rust 1.83.0 and later. Looks like Tailwind recently updated Rust versions and this issue started appearing when run in tools like Parcel that use worker threads. The workaround is to prevent the native module from ever being unloaded. One way to do that is to always load the native module in the main thread in addition to workers, but this is hard to enforce. @Brooooooklyn found another method, which is to use a linker option for this. I tested this on an Ubuntu system and verified it fixed the issue. You can test with the following script. ```js // test.js const {Worker} = require('worker_threads'); new Worker('./worker.js'); // worker.js require('@tailwindcss/oxide'); ``` Without this change, a segmentation fault will occur. --------- Co-authored-by: Jordan Pittman <[email protected]>
1 parent 1564bf0 commit db1a7d4

File tree

6 files changed

+44
-8
lines changed

6 files changed

+44
-8
lines changed

.github/workflows/integration-tests.yml

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ jobs:
3030
- vite
3131
- cli
3232
- postcss
33+
- workers
3334

3435
# Exclude windows and macos from being built on feature branches
3536
on-main-branch:

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2727
- Use the `oklab(…)` function when applying opacity to `currentColor` to work around a crash in Safari 16.4 and 16.5 ([#17247](https://github.com/tailwindlabs/tailwindcss/pull/17247))
2828
- Pre-process `<template lang="…">` in Vue files ([#17252](https://github.com/tailwindlabs/tailwindcss/pull/17252))
2929
- Remove redundant `line-height: initial` from Preflight ([#15212](https://github.com/tailwindlabs/tailwindcss/pull/15212))
30+
- Prevent segfault when loaded in a worker thread on Linux ([#17276](https://github.com/tailwindlabs/tailwindcss/pull/17276))
31+
- Increase Standalone hardware compatibility on macOS x64 builds ([#17267](https://github.com/tailwindlabs/tailwindcss/pull/17267))
3032

3133
## [4.0.14] - 2025-03-13
3234

crates/node/.cargo/config.toml

+2
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ linker = "arm-linux-gnueabihf-gcc"
1010
rustflags = ["-C", "target-feature=+crt-static"]
1111
[target.aarch64-pc-windows-msvc]
1212
rustflags = ["-C", "target-feature=+crt-static"]
13+
[target.'cfg(target_env = "gnu")']
14+
rustflags = ["-C", "link-args=-Wl,-z,nodelete"]

integrations/workers/index.test.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { js, json, test } from '../utils'
2+
3+
test(
4+
'@tailwindcss/oxide can be loaded into a Node.js worker thread',
5+
{
6+
fs: {
7+
'package.json': json`
8+
{
9+
"dependencies": {
10+
"@tailwindcss/oxide": "workspace:^"
11+
}
12+
}
13+
`,
14+
'start.js': js`
15+
let { Worker } = require('worker_threads')
16+
new Worker('./worker.js')
17+
`,
18+
'worker.js': js`
19+
require('@tailwindcss/oxide')
20+
process.on('exit', () => console.log('worker thread exited'))
21+
`,
22+
},
23+
},
24+
async ({ exec, expect }) => {
25+
let output = await exec('node ./start.js').then(
26+
(out) => out.trim(),
27+
(err) => `${err}`,
28+
)
29+
30+
expect(output).toEqual('worker thread exited')
31+
},
32+
)

packages/@tailwindcss-standalone/scripts/build.ts

+5-8
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ async function buildForPlatform(triple: string, outfile: string) {
1212
try {
1313
let cmd = $`bun build --compile --target=${triple} ./src/index.ts --outfile=${outfile} --env inline`
1414

15-
// This env var is used by our patched versions of Lightning CSS and Parcel Watcher
16-
// to statically bundle the proper binaries for musl vs glibc
15+
// This env var is used by our patched versions of Lightning CSS and Parcel Watcher to
16+
// statically bundle the proper binaries for musl vs glibc
1717
cmd = cmd.env({
1818
PLATFORM_LIBC: triple.includes('-musl') ? 'musl' : 'glibc',
1919
})
@@ -51,21 +51,18 @@ async function build(triple: string, file: string) {
5151

5252
await mkdir(path.resolve(__dirname, '../dist'), { recursive: true })
5353

54-
// Build platform binaries and checksum them
54+
// Build platform binaries and checksum them. We use baseline builds for all x64 platforms to ensure
55+
// compatibility with older hardware.
5556
let results = await Promise.all([
5657
build('bun-linux-arm64', './tailwindcss-linux-arm64'),
5758
build('bun-linux-arm64-musl', './tailwindcss-linux-arm64-musl'),
5859

59-
// All Linux x64 builds use `bun-baseline` due to various instruction-related
60-
// errors on some older Server hardware.
6160
build('bun-linux-x64-baseline', './tailwindcss-linux-x64'),
6261
build('bun-linux-x64-musl-baseline', './tailwindcss-linux-x64-musl'),
6362

6463
build('bun-darwin-arm64', './tailwindcss-macos-arm64'),
65-
build('bun-darwin-x64', './tailwindcss-macos-x64'),
64+
build('bun-darwin-x64-baseline', './tailwindcss-macos-x64'),
6665

67-
// The Windows x64 build uses `bun-baseline` instead of the regular bun build.
68-
// This enables support for running inside the ARM emulation mode.
6966
build('bun-windows-x64-baseline', './tailwindcss-windows-x64.exe'),
7067
])
7168

turbo.json

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"./build.rs",
1111
"./package.json",
1212
"./Cargo.toml",
13+
"./.cargo/config.toml",
1314
"../oxide/src/**/*",
1415
"../oxide/Cargo.toml",
1516
"../Cargo.toml",
@@ -24,6 +25,7 @@
2425
"./build.rs",
2526
"./package.json",
2627
"./Cargo.toml",
28+
"./.cargo/config.toml",
2729
"../oxide/src/**/*",
2830
"../oxide/Cargo.toml",
2931
"../Cargo.toml",

0 commit comments

Comments
 (0)