是否有任何编程方式可以打破 NodeJS 中的无限循环?
Is there any programmatic way to break infinite loop in NodeJS?
归根结底 - 是否有一种实用的方法(也可能通过在代码中插入一些 JS 结构)在执行期间中断或停止持久的 JS 代码?例如:它可以被一些 process.*
对象结构或类似的东西打断吗?或者相反?有效的解决方案甚至可能包括 NodeJS 进程被杀死 and/or 重新启动。谢谢!
编辑:
我需要在服务器上执行一些特定的用户代码,使用 Function
子句(ala eval
,更不用说安全问题了)。我不能在其中插入任何额外的代码,只能将其括起来。我需要的是有可能在 5 分钟后破坏用户代码,如果此时还没有完成的话。例如:
usercode = 'Some code from the user';
pre_code = 'some controlling code for breaking the user code';
post_code = 'another controlling code';
fcode = pre_code + usercode + post_code;
<preparations for breaking usercode>
(new Function(fcode))(); // This MUST exit in 5 minutes
编辑:
正在回答您的编辑。我现在明白了意图。如果它是nodejs中的运行,你可以使用worker_thread来表示https://nodejs.org/api/worker_threads.html#worker_threads_worker_workerdata。
例如:
// main.js
const runCode = (code) => {
const worker = new Worker("./code-executor.js", { workerData: { code: guestCode } });
const promise = new Promise((resolve) => {
setTimeout(() => worker.kill(), 60000 * 5);
worker.on("error", () => {
return reject(new SomeCustomError())
});
worker.on("message", (message) => {
if(message.success) return resolve(message.result);
return reject(new Error(message.error));
});
});
promise.finally(() => { worker.kill() });
return promise;
}
// code-executor.js
const { workerData, parentPort } = require("worker_threads");
const { code } = workerData;
Promise.resolve()
.then(() => (new Function(fcode))())
.then((result) => {
parentPort.postMessage({
success: true,
result: value
})
})
.catch((error) => {
parentPort.postMessage({
success: true,
error: error.message
})
});
如果在浏览器中 https://developer.mozilla.org/en-US/docs/Web/API/Worker
WebAPI不完全相同,但逻辑应该相似
原创
正在终止进程。另请阅读:https://nodejs.org/api/process.html#process_signal_events
process.kill(pid, "SIGINT")
"Killing" 一个很长的 运行 函数,你得破解一下。没有优雅的解决方案。注入一个可以在 long 运行 函数之外改变的控制器。要从外部停止它,请设置 controller.isStopped = true
export const STOP_EXECUTION = Symbol();
function longRunning(controller){
... codes
// add stopping point
if(controller.isStopped) throw STOP_EXECUTION;
... codes
// add stopping point
if(controller.isStopped) throw STOP_EXECUTION;
... codes
}
// catch it by
try{
longRunnning();
}catch(e){
switch(true){
e === STOP_EXECUTION: ...; // the longRunning function is stopped from the outside
default: ...; // the longRunning function is throwing not because of being stopped
}
}
要点:https://gist.github.com/Kelerchian/3824ca4ce1be390d34c5147db671cc9b
归根结底 - 是否有一种实用的方法(也可能通过在代码中插入一些 JS 结构)在执行期间中断或停止持久的 JS 代码?例如:它可以被一些 process.*
对象结构或类似的东西打断吗?或者相反?有效的解决方案甚至可能包括 NodeJS 进程被杀死 and/or 重新启动。谢谢!
编辑:
我需要在服务器上执行一些特定的用户代码,使用 Function
子句(ala eval
,更不用说安全问题了)。我不能在其中插入任何额外的代码,只能将其括起来。我需要的是有可能在 5 分钟后破坏用户代码,如果此时还没有完成的话。例如:
usercode = 'Some code from the user';
pre_code = 'some controlling code for breaking the user code';
post_code = 'another controlling code';
fcode = pre_code + usercode + post_code;
<preparations for breaking usercode>
(new Function(fcode))(); // This MUST exit in 5 minutes
编辑:
正在回答您的编辑。我现在明白了意图。如果它是nodejs中的运行,你可以使用worker_thread来表示https://nodejs.org/api/worker_threads.html#worker_threads_worker_workerdata。
例如:
// main.js
const runCode = (code) => {
const worker = new Worker("./code-executor.js", { workerData: { code: guestCode } });
const promise = new Promise((resolve) => {
setTimeout(() => worker.kill(), 60000 * 5);
worker.on("error", () => {
return reject(new SomeCustomError())
});
worker.on("message", (message) => {
if(message.success) return resolve(message.result);
return reject(new Error(message.error));
});
});
promise.finally(() => { worker.kill() });
return promise;
}
// code-executor.js
const { workerData, parentPort } = require("worker_threads");
const { code } = workerData;
Promise.resolve()
.then(() => (new Function(fcode))())
.then((result) => {
parentPort.postMessage({
success: true,
result: value
})
})
.catch((error) => {
parentPort.postMessage({
success: true,
error: error.message
})
});
如果在浏览器中 https://developer.mozilla.org/en-US/docs/Web/API/Worker WebAPI不完全相同,但逻辑应该相似
原创
正在终止进程。另请阅读:https://nodejs.org/api/process.html#process_signal_events
process.kill(pid, "SIGINT")
"Killing" 一个很长的 运行 函数,你得破解一下。没有优雅的解决方案。注入一个可以在 long 运行 函数之外改变的控制器。要从外部停止它,请设置 controller.isStopped = true
export const STOP_EXECUTION = Symbol();
function longRunning(controller){
... codes
// add stopping point
if(controller.isStopped) throw STOP_EXECUTION;
... codes
// add stopping point
if(controller.isStopped) throw STOP_EXECUTION;
... codes
}
// catch it by
try{
longRunnning();
}catch(e){
switch(true){
e === STOP_EXECUTION: ...; // the longRunning function is stopped from the outside
default: ...; // the longRunning function is throwing not because of being stopped
}
}
要点:https://gist.github.com/Kelerchian/3824ca4ce1be390d34c5147db671cc9b