Skip to content

Commit eecc726

Browse files
committed
Fix POSIX implementation for Linux CI tests
- Use libuv for CPU and network interface info on POSIX - Add trusted_space heap spaces to match Node.js - Implement sharedObjects enumeration for Linux/macOS - Fixes test failures on Linux CI
1 parent 2880b90 commit eecc726

File tree

1 file changed

+133
-5
lines changed

1 file changed

+133
-5
lines changed

src/bun.js/bindings/BunProcess.cpp

Lines changed: 133 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
#include "JavaScriptCore/JSGlobalObjectDebuggable.h"
3737
#include <JavaScriptCore/StackFrame.h>
3838
#include <sys/stat.h>
39+
#include <unordered_set>
40+
#if OS(DARWIN)
41+
#include <mach-o/dyld.h>
42+
#endif
3943
#include "ConsoleObject.h"
4044
#include <JavaScriptCore/GetterSetter.h>
4145
#include <JavaScriptCore/JSSet.h>
@@ -2394,9 +2398,91 @@ static JSValue constructReportObjectComplete(VM& vm, Zig::GlobalObject* globalOb
23942398
#endif
23952399
#endif
23962400

2397-
header->putDirect(vm, Identifier::fromString(vm, "cpus"_s), JSC::constructEmptyArray(globalObject, nullptr), 0);
2398-
RETURN_IF_EXCEPTION(scope, {});
2399-
header->putDirect(vm, Identifier::fromString(vm, "networkInterfaces"_s), JSC::constructEmptyArray(globalObject, nullptr), 0);
2401+
// Use libuv to get CPU info
2402+
{
2403+
uv_cpu_info_t* cpu_infos;
2404+
int count;
2405+
if (uv_cpu_info(&cpu_infos, &count) == 0) {
2406+
JSC::JSArray* cpuArray = JSC::constructEmptyArray(globalObject, nullptr, count);
2407+
RETURN_IF_EXCEPTION(scope, {});
2408+
2409+
for (int i = 0; i < count; i++) {
2410+
JSC::JSObject* cpu = JSC::constructEmptyObject(globalObject);
2411+
cpu->putDirect(vm, JSC::Identifier::fromString(vm, "model"_s), JSC::jsString(vm, String::fromUTF8(cpu_infos[i].model)), 0);
2412+
cpu->putDirect(vm, JSC::Identifier::fromString(vm, "speed"_s), JSC::jsNumber(cpu_infos[i].speed), 0);
2413+
2414+
JSC::JSObject* times = JSC::constructEmptyObject(globalObject);
2415+
times->putDirect(vm, JSC::Identifier::fromString(vm, "user"_s), JSC::jsNumber(cpu_infos[i].cpu_times.user), 0);
2416+
times->putDirect(vm, JSC::Identifier::fromString(vm, "nice"_s), JSC::jsNumber(cpu_infos[i].cpu_times.nice), 0);
2417+
times->putDirect(vm, JSC::Identifier::fromString(vm, "sys"_s), JSC::jsNumber(cpu_infos[i].cpu_times.sys), 0);
2418+
times->putDirect(vm, JSC::Identifier::fromString(vm, "idle"_s), JSC::jsNumber(cpu_infos[i].cpu_times.idle), 0);
2419+
times->putDirect(vm, JSC::Identifier::fromString(vm, "irq"_s), JSC::jsNumber(cpu_infos[i].cpu_times.irq), 0);
2420+
2421+
cpu->putDirect(vm, JSC::Identifier::fromString(vm, "times"_s), times, 0);
2422+
cpuArray->putDirectIndex(globalObject, i, cpu);
2423+
}
2424+
header->putDirect(vm, Identifier::fromString(vm, "cpus"_s), cpuArray, 0);
2425+
uv_free_cpu_info(cpu_infos, count);
2426+
} else {
2427+
header->putDirect(vm, Identifier::fromString(vm, "cpus"_s), JSC::constructEmptyArray(globalObject, nullptr), 0);
2428+
}
2429+
RETURN_IF_EXCEPTION(scope, {});
2430+
}
2431+
2432+
// Use libuv to get network interfaces
2433+
{
2434+
uv_interface_address_t* interfaces;
2435+
int count;
2436+
if (uv_interface_addresses(&interfaces, &count) == 0) {
2437+
JSC::JSArray* interfacesArray = JSC::constructEmptyArray(globalObject, nullptr, count);
2438+
RETURN_IF_EXCEPTION(scope, {});
2439+
2440+
for (int i = 0; i < count; i++) {
2441+
JSC::JSObject* iface = JSC::constructEmptyObject(globalObject);
2442+
iface->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), JSC::jsString(vm, String::fromUTF8(interfaces[i].name)), 0);
2443+
iface->putDirect(vm, JSC::Identifier::fromString(vm, "internal"_s), JSC::jsBoolean(interfaces[i].is_internal), 0);
2444+
2445+
char addr[INET6_ADDRSTRLEN];
2446+
if (interfaces[i].address.address4.sin_family == AF_INET) {
2447+
uv_inet_ntop(AF_INET, &interfaces[i].address.address4.sin_addr, addr, sizeof(addr));
2448+
iface->putDirect(vm, JSC::Identifier::fromString(vm, "address"_s), JSC::jsString(vm, String::fromUTF8(addr)), 0);
2449+
2450+
char netmask[INET_ADDRSTRLEN];
2451+
uv_inet_ntop(AF_INET, &interfaces[i].netmask.netmask4.sin_addr, netmask, sizeof(netmask));
2452+
iface->putDirect(vm, JSC::Identifier::fromString(vm, "netmask"_s), JSC::jsString(vm, String::fromUTF8(netmask)), 0);
2453+
2454+
iface->putDirect(vm, JSC::Identifier::fromString(vm, "family"_s), JSC::jsString(vm, String::fromLatin1("IPv4")), 0);
2455+
} else if (interfaces[i].address.address6.sin6_family == AF_INET6) {
2456+
uv_inet_ntop(AF_INET6, &interfaces[i].address.address6.sin6_addr, addr, sizeof(addr));
2457+
iface->putDirect(vm, JSC::Identifier::fromString(vm, "address"_s), JSC::jsString(vm, String::fromUTF8(addr)), 0);
2458+
2459+
char netmask[INET6_ADDRSTRLEN];
2460+
uv_inet_ntop(AF_INET6, &interfaces[i].netmask.netmask6.sin6_addr, netmask, sizeof(netmask));
2461+
iface->putDirect(vm, JSC::Identifier::fromString(vm, "netmask"_s), JSC::jsString(vm, String::fromUTF8(netmask)), 0);
2462+
2463+
iface->putDirect(vm, JSC::Identifier::fromString(vm, "family"_s), JSC::jsString(vm, String::fromLatin1("IPv6")), 0);
2464+
iface->putDirect(vm, JSC::Identifier::fromString(vm, "scopeid"_s), JSC::jsNumber(interfaces[i].address.address6.sin6_scope_id), 0);
2465+
}
2466+
2467+
// MAC address
2468+
char mac[18];
2469+
snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
2470+
static_cast<unsigned char>(interfaces[i].phys_addr[0]),
2471+
static_cast<unsigned char>(interfaces[i].phys_addr[1]),
2472+
static_cast<unsigned char>(interfaces[i].phys_addr[2]),
2473+
static_cast<unsigned char>(interfaces[i].phys_addr[3]),
2474+
static_cast<unsigned char>(interfaces[i].phys_addr[4]),
2475+
static_cast<unsigned char>(interfaces[i].phys_addr[5]));
2476+
iface->putDirect(vm, JSC::Identifier::fromString(vm, "mac"_s), JSC::jsString(vm, String::fromUTF8(mac)), 0);
2477+
2478+
interfacesArray->putDirectIndex(globalObject, i, iface);
2479+
}
2480+
header->putDirect(vm, Identifier::fromString(vm, "networkInterfaces"_s), interfacesArray, 0);
2481+
uv_free_interface_addresses(interfaces, count);
2482+
} else {
2483+
header->putDirect(vm, Identifier::fromString(vm, "networkInterfaces"_s), JSC::constructEmptyArray(globalObject, nullptr), 0);
2484+
}
2485+
}
24002486
RETURN_IF_EXCEPTION(scope, {});
24012487

24022488
return header;
@@ -2425,6 +2511,10 @@ static JSValue constructReportObjectComplete(VM& vm, Zig::GlobalObject* globalOb
24252511
RETURN_IF_EXCEPTION(scope, {});
24262512
heapSpaces->putDirect(vm, JSC::Identifier::fromString(vm, "shared_large_object_space"_s), JSC::constructEmptyObject(globalObject), 0);
24272513
RETURN_IF_EXCEPTION(scope, {});
2514+
heapSpaces->putDirect(vm, JSC::Identifier::fromString(vm, "trusted_space"_s), JSC::constructEmptyObject(globalObject), 0);
2515+
RETURN_IF_EXCEPTION(scope, {});
2516+
heapSpaces->putDirect(vm, JSC::Identifier::fromString(vm, "trusted_large_object_space"_s), JSC::constructEmptyObject(globalObject), 0);
2517+
RETURN_IF_EXCEPTION(scope, {});
24282518

24292519
heap->putDirect(vm, JSC::Identifier::fromString(vm, "totalMemory"_s), JSC::jsNumber(WTF::ramSize()), 0);
24302520
heap->putDirect(vm, JSC::Identifier::fromString(vm, "executableMemory"_s), jsNumber(0), 0);
@@ -2466,10 +2556,48 @@ static JSValue constructReportObjectComplete(VM& vm, Zig::GlobalObject* globalOb
24662556
};
24672557

24682558
auto constructSharedObjects = [&]() -> JSC::JSValue {
2469-
JSC::JSObject* sharedObjects = JSC::constructEmptyArray(globalObject, nullptr);
2559+
JSC::JSArray* sharedObjects = JSC::constructEmptyArray(globalObject, nullptr);
24702560
RETURN_IF_EXCEPTION(scope, {});
24712561

2472-
// TODO:
2562+
#if OS(LINUX)
2563+
// Read /proc/self/maps to find loaded shared objects
2564+
FILE* maps = fopen("/proc/self/maps", "r");
2565+
if (maps) {
2566+
char line[1024];
2567+
std::unordered_set<std::string> libraries;
2568+
while (fgets(line, sizeof(line), maps)) {
2569+
char path[512];
2570+
if (sscanf(line, "%*s %*s %*s %*s %*s %511s", path) == 1) {
2571+
if (strstr(path, ".so") != nullptr && path[0] == '/') {
2572+
libraries.insert(path);
2573+
}
2574+
}
2575+
}
2576+
fclose(maps);
2577+
2578+
int index = 0;
2579+
for (const auto& lib : libraries) {
2580+
sharedObjects->putDirectIndex(globalObject, index++, JSC::jsString(vm, String::fromUTF8(lib.c_str())));
2581+
}
2582+
}
2583+
#elif OS(DARWIN)
2584+
// Use dyld to enumerate loaded images
2585+
uint32_t count = _dyld_image_count();
2586+
for (uint32_t i = 0; i < count; i++) {
2587+
const char* name = _dyld_get_image_name(i);
2588+
if (name) {
2589+
sharedObjects->putDirectIndex(globalObject, i, JSC::jsString(vm, String::fromUTF8(name)));
2590+
}
2591+
}
2592+
#else
2593+
// For other platforms, at least add the main executable
2594+
char path[PATH_MAX];
2595+
ssize_t len = readlink("/proc/self/exe", path, sizeof(path) - 1);
2596+
if (len != -1) {
2597+
path[len] = '\0';
2598+
sharedObjects->putDirectIndex(globalObject, 0, JSC::jsString(vm, String::fromUTF8(path)));
2599+
}
2600+
#endif
24732601

24742602
return sharedObjects;
24752603
};

0 commit comments

Comments
 (0)