diff --git a/packages/optimizers/image/package.json b/packages/optimizers/image/package.json index 0eea76503b2..02dbe91e66d 100644 --- a/packages/optimizers/image/package.json +++ b/packages/optimizers/image/package.json @@ -35,6 +35,7 @@ "@parcel/diagnostic": "^2.0.1", "@parcel/plugin": "^2.0.1", "@parcel/utils": "^2.0.1", + "@parcel/workers": "^2.0.1", "detect-libc": "^1.0.3" }, "devDependencies": { diff --git a/packages/optimizers/image/src/ImageOptimizer.js b/packages/optimizers/image/src/ImageOptimizer.js index 5f4f506ffdc..a14664e6262 100644 --- a/packages/optimizers/image/src/ImageOptimizer.js +++ b/packages/optimizers/image/src/ImageOptimizer.js @@ -5,6 +5,7 @@ import {Optimizer} from '@parcel/plugin'; import {blobToBuffer} from '@parcel/utils'; import {md} from '@parcel/diagnostic'; import {optimize} from '../native'; +import WorkerFarm from '@parcel/workers'; export default (new Optimizer({ async optimize({bundle, contents, logger}) { @@ -12,6 +13,7 @@ export default (new Optimizer({ return {contents}; } + await loadOnMainThreadIfNeeded(); let buffer = await blobToBuffer(contents); // Attempt to optimize it, if the optimize fails we log a warning... @@ -34,3 +36,27 @@ export default (new Optimizer({ return {contents: buffer}; }, }): Optimizer); + +// On linux with older versions of glibc (e.g. CentOS 7), we encounter a segmentation fault +// when worker threads exit due to thread local variables in Rust. A workaround is to +// also load the native module on the main thread, so that it is not unloaded until process exit. +// See https://github.com/rust-lang/rust/issues/91979. +let isLoadedOnMainThread = false; +async function loadOnMainThreadIfNeeded() { + if ( + !isLoadedOnMainThread && + process.platform === 'linux' && + WorkerFarm.isWorker() + ) { + let {family, version} = require('detect-libc'); + if (family === 'glibc' && parseFloat(version) <= 2.17) { + let api = WorkerFarm.getWorkerApi(); + await api.callMaster({ + location: __dirname + '/loadNative.js', + args: [], + }); + + isLoadedOnMainThread = true; + } + } +} diff --git a/packages/optimizers/image/src/loadNative.js b/packages/optimizers/image/src/loadNative.js new file mode 100644 index 00000000000..d0795719bef --- /dev/null +++ b/packages/optimizers/image/src/loadNative.js @@ -0,0 +1,6 @@ +// This function is called from the main thread to prevent unloading the module +// until the main thread exits. This avoids a segfault in older glibc versions. +// See https://github.com/rust-lang/rust/issues/91979 +module.exports = () => { + require('../native'); +};