Skip to content

Commit

Permalink
zombie fix
Browse files Browse the repository at this point in the history
  • Loading branch information
timbrinded committed Nov 13, 2024
1 parent 3bccd15 commit d3214f7
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 247 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"pnpm": "9.12.3",
"semver": "7.6.2",
"solc": "0.8.28",
"tiny-invariant": "^1.3.3",
"tsup": "8.3.5",
"tsx": "4.19.2",
"viem": "2.21.44",
Expand Down
11 changes: 6 additions & 5 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"@polkadot/util": "*",
"@polkadot/util-crypto": "*",
"@vitest/ui": "*",
"@zombienet/orchestrator": "0.0.91",
"@zombienet/orchestrator": "0.0.97",
"@zombienet/utils": "*",
"bottleneck": "2.19.5",
"cfonts": "^3.3.0",
Expand All @@ -88,23 +88,24 @@
"jsonc-parser": "3.3.1",
"minimatch": "9.0.5",
"semver": "*",
"tiny-invariant": "*",
"viem": "*",
"vitest": "*",
"web3": "*",
"web3-providers-ws": "^4.0.7",
"ws": "*",
"yaml": "2.4.5",
"yargs": "*"
"yargs": "*"
},
"devDependencies": {
"@biomejs/biome": "1.9.2",
"@biomejs/biome": "*",
"@types/clear": "^0.1.4",
"@types/cli-progress": "3.11.6",
"@types/debug": "*",
"@types/node": "*",
"@types/semver": "*",
"@types/ws": "*",
"@types/yargs": "*",
"@types/ws": "*",
"@types/yargs": "*",
"tsup": "*",
"tsx": "*",
"typescript": "*"
Expand Down
12 changes: 8 additions & 4 deletions packages/cli/src/internal/foundations/zombieHelpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { LaunchConfig } from "@zombienet/orchestrator";
import chalk from "chalk";
import fs from "node:fs";
import invariant from "tiny-invariant";
import { checkAccess, checkExists } from "../fileCheckers";
import { setTimeout as timer } from "node:timers/promises";
import net from "node:net";
Expand Down Expand Up @@ -79,12 +80,15 @@ export async function sendIpcMessage(message: IPCRequestMessage): Promise<IPCRes
return new Promise(async (resolve, reject) => {
let response: IPCResponseMessage;
const ipcPath = process.env.MOON_IPC_SOCKET;
invariant(ipcPath, "No IPC path found. This is a bug, please report it.");

if (!ipcPath) {
throw new Error("No IPC path found. This is a bug, please report it.");
}
const client = net.createConnection({ path: ipcPath }, () => {
console.log("πŸ“¨ Successfully connected to IPC server");
});

const client = net.createConnection({ path: ipcPath });
client.on("error", (err) => {
console.error("πŸ“¨ IPC client connection error:", err);
});

// Listener to return control flow after server responds
client.on("data", async (data) => {
Expand Down
95 changes: 80 additions & 15 deletions packages/cli/src/lib/globalContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import fs from "node:fs";
import net from "node:net";
import readline from "node:readline";
import { setTimeout as timer } from "node:timers/promises";
import path from "node:path";
import { parseChopsticksRunCmd, parseRunCmd, parseZombieCmd } from "../internal/commandParsers";
import {
type IPCRequestMessage,
Expand Down Expand Up @@ -198,6 +199,14 @@ export class MoonwallContext {
await checkZombieBins(zombieConfig);

const network = await zombie.start("", zombieConfig, { logType: "silent" });
const ipcLogPath = path.join(network.tmpDir, "ipc-server.log");
const ipcLogger = fs.createWriteStream(ipcLogPath, { flags: "a" });

const logIpc = (message: string) => {
const timestamp = new Date().toISOString();
ipcLogger.write(`${timestamp} - ${message}\n`);
};

process.env.MOON_RELAY_WSS = network.relay[0].wsUri;
process.env.MOON_PARA_WSS = Object.values(network.paras)[0].nodes[0].wsUri;

Expand All @@ -224,20 +233,26 @@ export class MoonwallContext {
}
};

// Refactored IPC Server Implementation Starts Here
const socketPath = `${network.tmpDir}/node-ipc.sock`;

// Remove existing socket file if it exists to prevent EADDRINUSE errors
if (fs.existsSync(socketPath)) {
fs.unlinkSync(socketPath);
logIpc(`Removed existing socket at ${socketPath}`);
}

const server = net.createServer((client) => {
// client.on("end", () => {
// console.log("πŸ“¨ IPC client disconnected");
// });
logIpc("πŸ“¨ IPC server created");
logIpc(`Socket path: ${socketPath}`);

// Client message handling
client.on("data", async (data) => {
const writeToClient = (message: IPCResponseMessage) => {
if (client.writable) {
client.write(JSON.stringify(message));
} else {
console.log("Client disconnected, cannot send response.");
logIpc("Client disconnected, cannot send response.");
}
};

Expand All @@ -262,10 +277,36 @@ export class MoonwallContext {
}

case "restart": {
await this.disconnect();
await zombieClient.restartNode(message.nodeName, null);
await timer(1000); // TODO: Replace when zombienet has an appropriate fn
await this.connectEnvironment(true);
logIpc(`πŸ“¨ Restart command received for node: ${message.nodeName}`);
try {
await this.disconnect();
logIpc("βœ… Disconnected all providers.");
} catch (err) {
logIpc(`❌ Error during disconnect: ${err}`);
throw err;
}

try {
logIpc(`πŸ“¨ Restarting node: ${message.nodeName}`);
// Timeout is in seconds 🀦
await zombieClient.restartNode(message.nodeName, 5);
logIpc(`βœ… Restarted node: ${message.nodeName}`);
} catch (err) {
logIpc(`❌ Error during node restart: ${err}`);
throw err;
}

await timer(5000); // TODO: Replace when zombienet has an appropriate fn

try {
logIpc("πŸ”„ Reconnecting environment...");
await this.connectEnvironment();
logIpc("βœ… Reconnected environment.");
} catch (err) {
logIpc(`❌ Error during environment reconnection: ${err}`);
throw err;
}

writeToClient({
status: "success",
result: true,
Expand Down Expand Up @@ -305,12 +346,12 @@ export class MoonwallContext {
// await this.disconnect();
const pid = (network.client as any).processMap[message.nodeName].pid;
delete (network.client as any).processMap[message.nodeName];
const result = exec(`kill ${pid}`, { timeout: 1000 });
const killResult = execSync(`kill ${pid}`, { stdio: "ignore" });
// await this.connectEnvironment(true);
writeToClient({
status: "success",
result: result.exitCode === 0,
message: `${message.nodeName}, pid ${pid} killed with exitCode ${result.exitCode}`,
result: true,
message: `${message.nodeName}, pid ${pid} killed`,
});
break;
}
Expand All @@ -330,19 +371,41 @@ export class MoonwallContext {
throw new Error(`Invalid command received: ${message.cmd}`);
}
} catch (e: any) {
console.log("πŸ“¨ Error processing message from client:", data.toString());
console.error(e.message);
logIpc("πŸ“¨ Error processing message from client");
logIpc(e.message);
writeToClient({
status: "failure",
result: false,
message: e.message,
});
}
});

// Handle client errors
client.on("error", (err) => {
logIpc(`πŸ“¨ IPC client error:${err}`);
});

// Handle client disconnection
client.on("close", () => {
logIpc("πŸ“¨ IPC client disconnected");
});
});

// Handle server errors to prevent crashes
server.on("error", (err) => {
console.error("IPC Server error:", err);
});

server.listen(socketPath, () => {
console.log("πŸ“¨ IPC Server listening on", socketPath);
logIpc(`πŸ“¨ IPC Server attempting to listen on ${socketPath}`);
try {
fs.chmodSync(socketPath, 0o600);
logIpc("πŸ“¨ Successfully set socket permissions");
} catch (err) {
console.error("πŸ“¨ Error setting socket permissions:", err);
}
logIpc(`πŸ“¨ IPC Server listening on ${socketPath}`);
});

this.ipcServer = server;
Expand Down Expand Up @@ -624,7 +687,9 @@ export class MoonwallContext {

await waitForPidsToDie(processIds);

ctx.ipcServer?.close();
ctx.ipcServer?.close(() => {
console.log("IPC Server closed.");
});
ctx.ipcServer?.removeAllListeners();
}
}
Expand Down
Loading

0 comments on commit d3214f7

Please sign in to comment.