You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Promise.race对synchrony自定义函数失效,超时未触发异常排查

问题原因分析

问题出在synchrony.deobfuscateNode返回的Promise内部大概率是同步阻塞的CPU密集型操作——虽然它包装成了Promise,但内部逻辑是同步执行完才resolve,直接把Node.js的单线程事件循环卡死了。

Node.js的事件循环机制是:先执行完当前所有同步任务,才会去处理定时器、I/O回调这类异步队列的任务。所以当反混淆操作在同步占用CPU时,你设置的超时setTimeout回调根本没机会触发,必须等反混淆完全结束,定时器才会执行,但这时候Promise.race里的反混淆Promise已经resolve了,超时逻辑自然失效。

而你用testPromise测试时,内部是setTimeout异步任务,不会阻塞事件循环,所以超时定时器能正常触发,Promise.race能按预期工作。

解决方案

要解决这个问题,核心是把CPU密集的反混淆操作移出主线程,避免阻塞事件循环,常用的两种方式:

1. 使用Worker Threads(推荐)

Node.js的worker_threads模块可以把CPU密集任务放到单独的工作线程执行,主线程的事件循环不会被阻塞,超时逻辑就能正常运行。

步骤1:创建工作线程文件(比如deobfuscate.worker.js)

const { parentPort, workerData } = require('worker_threads');
const { Deobfuscator } = require('./synchrony');

async function run() {
  try {
    const synchrony = new Deobfuscator();
    const result = await synchrony.deobfuscateNode(workerData.ast);
    parentPort.postMessage({ success: true, data: result });
  } catch (err) {
    parentPort.postMessage({ success: false, error: err.message });
  }
}

run();

步骤2:修改主程序的callDeobfuscator函数

const { Worker } = require('worker_threads');
const { timeout } = require('../../../config');
const { parse } = require('../../utils/parser');

async function callDeobfuscator(ast) {
  const withTimeout = (promise) => {
    let timeoutPid;
    const timeoutPromise = new Promise((_, reject) => 
      timeoutPid = setTimeout(() => reject(new Error('反混淆超时')), timeout));
    return Promise.race([promise, timeoutPromise])
      .finally(() => timeoutPid && clearTimeout(timeoutPid));
  };

  // 用工作线程执行反混淆
  const workerPromise = new Promise((resolve, reject) => {
    const worker = new Worker('./deobfuscate.worker.js', {
      workerData: { ast }
    });

    worker.on('message', (msg) => {
      worker.terminate(); // 任务完成后终止工作线程
      if (msg.success) resolve(msg.data);
      else reject(new Error(msg.error));
    });

    worker.on('error', reject);
    worker.on('exit', (code) => {
      if (code !== 0) reject(new Error(`工作线程异常退出,代码:${code}`));
    });
  });

  return await withTimeout(workerPromise);
}

// 原读取文件逻辑补充错误处理
const fs = require('fs');
fs.readFile('script.js', 'utf8', async function(err, source){ 
  if (err) throw err;
  let ast = parse(source);
  try {
    ast = await callDeobfuscator(ast);
    console.log(ast);
  } catch (err) {
    console.error('操作失败:', err.message);
  }
});

2. 使用子进程(child_process)

如果你的Node.js版本较低(低于10.5.0,不支持worker_threads),可以用child_process.fork创建子进程来执行反混淆逻辑,原理和worker threads类似,都是把任务放到独立的执行环境,避免阻塞主线程。

额外建议

可以检查一下synchrony的官方文档,看看它是否内置了超时配置选项,或者有没有提供非阻塞的反混淆API,如果有的话,直接用内置功能会更简单。

内容的提问来源于stack exchange,提问作者GRoutar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 15:26:29