我有一个程序正在运行(
我们称之为A
),在里面,我打电话
child_process
从NodeJ运行另一个应用程序(
让我们称之为C
)。现在我不能改变它的结构,因为我们已经在这个模式中实现了很多功能。因此,任何调整都可能导致管道破裂。
现在我想使用CTRL+C终止那个C应用程序。由于这是一个二进制文件,我无法修改源代码,所以我需要向该程序发送Ctrl+C。我正在做这件事,它很高兴地结束了。
现在的问题是,它正在杀死C
以及A。
所以这是目前的主要问题。我尝试创建另一个中间程序
B
。但是它终止了C,然后终止了B,最后终止了A。所以Ctrl+C向上传播。如何防止Ctrl+C向上传播?
伪代码如下:
FUNCTION SigintWindows(args):
INITIALIZE isolate from args
Create new handle scope with isolate
GET processId from args[0]
OPEN process with processId If fails:
THROW Error("Failed to open process Error code: " + error code)
EXIT
TRY attaching to console If fails:
THROW Error("Failed to attach to console Error code: " + error code)
TRY sending Ctrl-C event directly If fails:
THROW Error("Failed to send Ctrl-C event Error code: " + error code)
CLOSE process handle
EXIT
ELSE:
SET return value to true
EXIT
ELSE:
DISABLE Ctrl-C handling for our program If fails:
THROW Error("Failed to disable Ctrl-C handling Error code: " + error code)
CLOSE process handle
EXIT
SEND Ctrl-C event If fails:
THROW Error("Failed to send Ctrl-C event Error code: " + error code)
RE-ENABLE Ctrl-C handling If fails:
THROW Error("Failed to re-enable Ctrl-C handling Error code: " + error code)
FREE the console
CLOSE process handle
EXIT
ELSE:
WAIT for the process to exit (max 2 seconds) If process doesn't exit:
THROW Error("Process did not exit within 2 seconds")
RE-ENABLE Ctrl-C handling If fails:
THROW Error("Failed to re-enable Ctrl-C handling Error code: " + error code)
FREE the console
CLOSE process handle
EXIT
END IF
RE-ENABLE Ctrl-C handling If fails:
THROW Error("Failed to re-enable Ctrl-C handling")
CLOSE process handle
EXIT
FREE the console
CLOSE process handle
SET return value to true
下面是整个C++实现:
#include <node.h>
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#include <windows.h>
#endif
namespace ctrlc {
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;
void SigintWindows(const v8::FunctionCallbackInfo < v8::Value > & args) {
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
v8::Isolate * isolate = args.GetIsolate();
v8::HandleScope scope(isolate);
// Check the number of arguments passed
if (args.Length() != 1) {
v8::Local < v8::String > v8String = v8::String::NewFromUtf8(isolate, "Invalid arguments").ToLocalChecked();
isolate -> ThrowException(v8::Exception::TypeError(v8String));
return;
}
// Check the argument types
if (!args[0] -> IsUint32()) {
v8::Local < v8::String > v8String = v8::String::NewFromUtf8(isolate, "Argument must be a number").ToLocalChecked();
isolate -> ThrowException(v8::Exception::TypeError(v8String));
return;
}
DWORD processId = args[0] -> Uint32Value(isolate -> GetCurrentContext()).ToChecked();
HANDLE hProcess = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, FALSE, processId);
if (hProcess == NULL) {
v8::Local<v8::String> v8String = v8::String::NewFromUtf8(isolate, ("Failed to open process. Error code: " + std::to_string(GetLastError())).c_str()).ToLocalChecked();
isolate->ThrowException(v8::Exception::Error(v8String));
return;
}
// Try to attach to console
if (!AttachConsole(processId)) {
v8::Local<v8::String> v8String = v8::String::NewFromUtf8(isolate, ("Failed to attach to console. Error code: " + std::to_string(GetLastError())).c_str()).ToLocalChecked();
isolate->ThrowException(v8::Exception::Error(v8String));
// If attaching to console fails, try sending Ctrl-C event directly
if (!GenerateConsoleCtrlEvent(CTRL_C_EVENT, processId)) {
v8::Local<v8::String> v8String = v8::String::NewFromUtf8(isolate, ("Failed to send Ctrl-C event. Error code: " + std::to_string(GetLastError())).c_str()).ToLocalChecked();
isolate->ThrowException(v8::Exception::Error(v8String));
CloseHandle(hProcess);
return;
} else {
args.GetReturnValue().Set(true);
return;
}
} else {
// Disable Ctrl-C handling for our program
if (!SetConsoleCtrlHandler(NULL, TRUE)) {
v8::Local<v8::String> v8String = v8::String::NewFromUtf8(isolate, ("Failed to disable Ctrl-C handling. Error code: " + std::to_string(GetLastError())).c_str()).ToLocalChecked();
isolate->ThrowException(v8::Exception::Error(v8String));
CloseHandle(hProcess);
return;
}
// Send Ctrl-C event
if (!GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)) {
v8::Local<v8::String> v8String = v8::String::NewFromUtf8(isolate, ("Failed to send Ctrl-C event. Error code: " + std::to_string(GetLastError())).c_str()).ToLocalChecked();
isolate->ThrowException(v8::Exception::Error(v8String));
// Re-enable Ctrl-C handling
if (!SetConsoleCtrlHandler(NULL, FALSE)) {
v8::Local<v8::String> v8String = v8::String::NewFromUtf8(isolate, ("Failed to re-enable Ctrl-C handling. Error code: " + std::to_string(GetLastError())).c_str()).ToLocalChecked();
isolate->ThrowException(v8::Exception::Error(v8String));
}
FreeConsole();
CloseHandle(hProcess);
return;
} else {
// Wait for process to exit
if (WaitForSingleObject(hProcess, 2000) != WAIT_OBJECT_0) {
v8::Local<v8::String> v8String = v8::String::NewFromUtf8(isolate, "Process did not exit within 2 seconds.").ToLocalChecked();
isolate->ThrowException(v8::Exception::Error(v8String));
}
// Re-enable Ctrl-C handling
if (!SetConsoleCtrlHandler(NULL, FALSE)) {
v8::Local<v8::String> v8String = v8::String::NewFromUtf8(isolate, ("Failed to re-enable Ctrl-C handling. Error code: " + std::to_string(GetLastError())).c_str()).ToLocalChecked();
isolate->ThrowException(v8::Exception::Error(v8String));
}
FreeConsole();
CloseHandle(hProcess);
return;
}
}
// Re-enable Ctrl-C handling
if (!SetConsoleCtrlHandler(NULL, FALSE)) {
v8::Local<v8::String> v8String = v8::String::NewFromUtf8(isolate, "Failed to re-enable Ctrl-C handling").ToLocalChecked();
isolate->ThrowException(v8::Exception::Error(v8String));
CloseHandle(hProcess);
return;
}
FreeConsole();
CloseHandle(hProcess);
args.GetReturnValue().Set(True(isolate));
#endif
}
void Init(Local < Object > exports) {
NODE_SET_METHOD(exports, "sigintWindows", SigintWindows);
}
NODE_MODULE(ctrlc, Init)
} // namespace ctrlc
请随时提供任何解决方案或建议。
注意:我试过分配一个处理程序,而不是“无”,但这也不起作用。