Skip to content

Instantly share code, notes, and snippets.

@sapphi-red
Created May 25, 2022 12:57
Show Gist options
  • Save sapphi-red/a0179b52ebd3b6a19f51743594810ecf to your computer and use it in GitHub Desktop.
Save sapphi-red/a0179b52ebd3b6a19f51743594810ecf to your computer and use it in GitHub Desktop.
Node.js eval worker Segmentation fault reproduction
import { Worker } from 'worker_threads'
function genWorkerCode(fn) {
return `
const doWork = ${fn.toString()}
const { parentPort } = require('worker_threads')
parentPort.on('message', async (args) => {
const res = await doWork(...args)
parentPort.postMessage(res)
})
`
}
// 10s after. 0-9s works well
const startAt = Date.now() + 10 * 1000
const fn = async (_startAt) => {
const until = new Date(_startAt).valueOf() - Date.now()
await new Promise((resolve) => setTimeout(resolve, until))
import('worker_threads') // fails
// require('worker_threads') // success
}
// same behavior when fn is string
/*
const fn = `async (_startAt) => {
const until = new Date(_startAt).valueOf() - Date.now()
await new Promise((resolve) => setTimeout(resolve, until))
import('worker_threads') // fails
// require('worker_threads') // success
}
`
*/
const code = genWorkerCode(fn)
const worker = new Worker(code, { eval: true })
worker.on('message', (res) => {
console.log('done', res)
worker.unref()
})
worker.on('error', (err) => {
console.error('error', err)
worker.unref()
})
worker.on('exit', (code) => {
console.log('exit', code)
})
worker.postMessage([startAt])
const { Worker } = require('worker_threads')
function genWorkerCode(fn) {
return `
const doWork = ${fn.toString()}
const { parentPort } = require('worker_threads')
parentPort.on('message', async (args) => {
const res = await doWork(...args)
parentPort.postMessage(res)
})
`
}
// 10s after. 0-9s works well
const startAt = Date.now() + 10 * 1000
const fn = async (_startAt) => {
const until = new Date(_startAt).valueOf() - Date.now()
await new Promise((resolve) => setTimeout(resolve, until))
import('worker_threads') // fails
// require('worker_threads') // success
}
// same behavior when fn is string
/*
const fn = `async (_startAt) => {
const until = new Date(_startAt).valueOf() - Date.now()
await new Promise((resolve) => setTimeout(resolve, until))
import('worker_threads') // fails
// require('worker_threads') // success
}
`
*/
const code = genWorkerCode(fn)
const worker = new Worker(code, { eval: true })
worker.on('message', (res) => {
console.log('done', res)
worker.unref()
})
worker.on('error', (err) => {
console.error('error', err)
worker.unref()
})
worker.on('exit', (code) => {
console.log('exit', code)
})
worker.postMessage([startAt])
import { Worker } from 'worker_threads'
// 10s after.
const startAt = Date.now() + 10 * 1000
const worker = new Worker('./worker.js')
worker.on('message', (res) => {
console.log('done', res)
worker.unref()
})
worker.on('error', (err) => {
console.error('error', err)
worker.unref()
})
worker.on('exit', (code) => {
console.log('exit', code)
})
worker.postMessage([startAt])
import { Worker } from 'worker_threads'
// 10s after.
const startAt = Date.now() + 10 * 1000
const worker = new Worker('./workerm.mjs')
worker.on('message', (res) => {
console.log('done', res)
worker.unref()
})
worker.on('error', (err) => {
console.error('error', err)
worker.unref()
})
worker.on('exit', (code) => {
console.log('exit', code)
})
worker.postMessage([startAt])
{
"name": "po",
"version": "1.0.0",
"description": "",
"author": "sapphi-red"
}
const doWork = async (_startAt) => {
const until = new Date(_startAt).valueOf() - Date.now()
await new Promise((resolve) => setTimeout(resolve, until))
import('worker_threads') // success
// require('worker_threads') // success
}
const { parentPort } = require('worker_threads')
parentPort.on('message', async (args) => {
const res = await doWork(...args)
parentPort.postMessage(res)
})
import { parentPort } from 'worker_threads'
const doWork = async (_startAt) => {
const until = new Date(_startAt).valueOf() - Date.now()
await new Promise((resolve) => setTimeout(resolve, until))
import('worker_threads') // success
}
parentPort.on('message', async (args) => {
const res = await doWork(...args)
parentPort.postMessage(res)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment