Wenn Node.js als Server verwendet wird, erstellt es ein Windows-Named-Pipe-Objekt und übergibt dies als Dateideskriptor 3 an den untergeordneten Prozess:
- https://github.com/nodejs/node/blob/mai ... ss.js#L162
- https://github.com/nodejs/node/blob/639 ... ss.js#L381
Angesichts des folgenden Node.js-Programms:
Code: Select all
const { spawn } = require('child_process');
const child = spawn('child.exe', [], {
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
env: env
});
child.on('message', (message) => {
let m = JSON.stringify(message);
console.log(`message from child: ${m}`)
});
child.send({foo: 123, bar: "456"});
Code: Select all
int main(int argc, char **argv)
{
HANDLE h = _get_osfhandle(3);
...
WriteFile(h, etc...);
...
ReadFile(h, etc...);
}
Jetzt versuche ich das Gegenteil: von einem C++-Host aus erstellen und übergeben die richtigen Datenstrukturen, um sicherzustellen, dass das Richtige als fd 3 in der fd-Tabelle des untergeordneten Prozesses landet.
Leider kann ich dies nicht replizieren:
Auf dem übergeordneten Prozess , ich erstelle meine Pipe so:
Code: Select all
static constexpr auto PIPENAME = "\\\\?\\pipe\\echo.sock";
OVERLAPPED overlapped = {0};
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof sa;
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
HANDLE serverPipeHandle = CreateNamedPipeA(PIPENAME,
PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
| WRITE_DAC
| FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_BYTE
| PIPE_READMODE_BYTE
| PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
65536,
65536,
0,
&sa);
if (serverPipeHandle == INVALID_HANDLE_VALUE) {
printf("CreateNamedPipe failed, GLE=%lu.\n", GetLastError());
return 1;
}
HANDLE client_pipe;
client_pipe = CreateFileA(PIPENAME,
GENERIC_READ | GENERIC_WRITE | WRITE_DAC,
0,
&sa,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
if (!ConnectNamedPipe(serverPipeHandle, NULL)) {
if (GetLastError() != ERROR_PIPE_CONNECTED) {
printf("ConnectNamedPipe failed, GLE=%lu.\n", GetLastError());
}
}
Code: Select all
auto h = _open_osfhandle((intptr_t) serverPipeHandle, 0);
// Prints: Handle=276 (or sometimes 260 or close numbers)
fprintf(stderr, "Handle=%llu \n", (std::uintptr_t) serverPipeHandle);
// Always prints: fd=3
fprintf(stderr, "fd=%d \n", h);
Code: Select all
STARTUPINFOA si = {0};
ZeroMemory(&si, sizeof(STARTUPINFOA));
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {0};
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
CreateProcess(NULL, app, NULL, NULL,
TRUE, // handle inheritance
CREATE_SUSPENDED, NULL, NULL,
&si, &pi);
ResumeThread(pi.hThread);
Was fehlt mir, um es verfügbar zu machen?
I versucht:
- Markieren Sie die Handles explizit als erben, bevor Sie den Prozess erstellen:
Code: Select all
SetHandleInformation(serverPipeHandle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
SetHandleInformation(client_pipe, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
- DuplicateHandle nach CreateProcess und vor ResumeThread aufrufen:
Code: Select all
HANDLE hFileDup;
DuplicateHandle(GetCurrentProcess(),
serverPipeHandle,
pi.hProcess,
&hFileDup,
0,
TRUE,
DUPLICATE_SAME_ACCESS);
- Aufrufen der CreateProcessWithExplicitHandles beschrieben in https://devblogs.microsoft.com/oldnewth ... 00/?p=8873 mit einem Array von Handles, die sowohl das Handle von CreateNamedPipeA als auch von CreateFileA enthalten.
- Es wird versucht, jedes fd in zu öffnen den untergeordneten Prozess, um zu sehen, ob der fd woanders hingehen würde:
Code: Select all
for (int i = -1000; i < 1000; i++) {
auto hFile = (HANDLE) _get_osfhandle(i);
if (hFile != INVALID_HANDLE_VALUE) {
fprintf(stderr, "Trying %d ...", i);
fprintf(stderr, "success! \n");
}
}
Code: Select all
Trying 0 ...success!
Trying 1 ...success!
Trying 2 ...success!
- Übergabe des rohen HANDLE-Werts an meinen untergeordneten Prozess (z. B. 260 statt 3). Das funktioniert, stimmt aber leider nicht mit der node.js-API überein.