Skip to content
This repository was archived by the owner on Jun 18, 2021. It is now read-only.

Commit 22ef3b2

Browse files
gabylbrichardlau
authored andcommitted
Add support for z/OS (#129)
PR-URL: #129 Reviewed-By: Richard Lau <riclau@uk.ibm.com>
1 parent 9462088 commit 22ef3b2

4 files changed

Lines changed: 105 additions & 5 deletions

File tree

binding.gyp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
"libraries": [ "dbghelp.lib", "Netapi32.lib", "PsApi.lib", "Ws2_32.lib" ],
1414
"dll_files": [ "dbghelp.dll", "Netapi32.dll", "PsApi.dll", "Ws2_32.dll" ],
1515
}],
16+
["OS=='zos'", {
17+
"cflags!": [ "-O2", "-O3" ],
18+
"cflags": [ "-qascii" ],
19+
}],
1620
],
1721
"defines": [
1822
'NODEREPORT_VERSION="<!(node -p \"require(\'./package.json\').version\")"'

src/node_report.cc

100644100755
Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#endif
3535
// Include execinfo.h for the native backtrace API. The API is unavailable on AIX
3636
// and on some Linux distributions, e.g. Alpine Linux.
37-
#if !defined(_AIX) && !(defined(__linux__) && !defined(__GLIBC__))
37+
#if !defined(_AIX) && !(defined(__linux__) && !defined(__GLIBC__)) && !defined(__MVS__)
3838
#include <execinfo.h>
3939
#endif
4040
#include <sys/utsname.h>
@@ -48,6 +48,20 @@
4848
extern char** environ;
4949
#endif
5050

51+
#ifdef __MVS__
52+
class __auto_ascii {
53+
public:
54+
__auto_ascii();
55+
~__auto_ascii();
56+
};
57+
extern "C" int backtrace(void **buffer, int size);
58+
extern "C" char **backtrace_symbols(void *const *buffer, int size);
59+
extern "C" void *__dlcb_next(void *last);
60+
extern "C" int __dlcb_entry_name(char *buf, int size, void *dlcb);
61+
extern "C" void *__dlcb_entry_addr(void *dlcb);
62+
extern "C" int __find_file_in_path(char *out, int size, const char *envvar, const char *file);
63+
#endif
64+
5165
namespace nodereport {
5266

5367
using v8::HeapSpaceStatistics;
@@ -138,6 +152,9 @@ void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, c
138152
}
139153

140154
// Open the report file stream for writing. Supports stdout/err, user-specified or (default) generated name
155+
#ifdef __MVS__
156+
__auto_ascii _a;
157+
#endif
141158
std::ofstream outfile;
142159
std::ostream* outstream = &std::cout;
143160
if (!strncmp(filename, "stdout", sizeof("stdout") - 1)) {
@@ -420,12 +437,29 @@ static void PrintVersionInformation(std::ostream& out) {
420437
out << "\nOS version: " << os_info.sysname << " " << os_info.release << " "
421438
<< os_info.version << "\n";
422439
#endif
440+
#if defined(__MVS__)
441+
char *r;
442+
__asm(" llgt %0,1208 \n"
443+
" lg %0,88(%0) \n"
444+
" lg %0,8(%0) \n"
445+
" lg %0,984(%0) \n"
446+
: "=r"(r)::);
447+
if (r != NULL) {
448+
const char *prod = (int)r[80]==4 ? " (MVS LE)" : "";
449+
out << "\nProduct " << (int)r[80] << prod << " Version " << (int)r[81] << " Release " << (int)r[82] << " Modification " << (int)r[83] << std::endl;
450+
}
451+
char hn[256];
452+
memset(hn,0,sizeof(hn));
453+
gethostname(hn,sizeof(hn));
454+
out << "\nMachine: " << hn << " " << os_info.nodename << " " << os_info.machine << "\n";
455+
#else
423456
const char *(*libc_version)();
424457
*(void**)(&libc_version) = dlsym(RTLD_DEFAULT, "gnu_get_libc_version");
425458
if (libc_version != NULL) {
426459
out << "(glibc: " << (*libc_version)() << ")" << std::endl;
427460
}
428461
out << "\nMachine: " << os_info.nodename << " " << os_info.machine << "\n";
462+
#endif
429463
}
430464
#endif
431465
}
@@ -694,6 +728,16 @@ void PrintNativeStack(std::ostream& out) {
694728
return;
695729
}
696730

731+
#ifdef __MVS__
732+
char **res = backtrace_symbols(frames, size);
733+
if (!res)
734+
return;
735+
for (int i = 0; i < size; i++) {
736+
// print traceback symbols and addresses
737+
out << res[i] << std::endl;
738+
}
739+
free(res);
740+
#else
697741
// Print the native frames, omitting the top 3 frames as they are in node-report code
698742
// backtrace_symbols_fd(frames, size, fileno(fp));
699743
for (int i = 2; i < size; i++) {
@@ -717,6 +761,7 @@ void PrintNativeStack(std::ostream& out) {
717761
}
718762
out << std::endl;
719763
}
764+
#endif
720765
}
721766
#endif
722767

@@ -786,7 +831,7 @@ static void PrintResourceUsage(std::ostream& out) {
786831
struct rusage stats;
787832
out << "\nProcess total resource usage:";
788833
if (getrusage(RUSAGE_SELF, &stats) == 0) {
789-
#if defined(__APPLE__) || defined(_AIX)
834+
#if defined(__APPLE__) || defined(_AIX) || defined(__MVS__)
790835
snprintf( buf, sizeof(buf), "%ld.%06d", stats.ru_utime.tv_sec, stats.ru_utime.tv_usec);
791836
out << "\n User mode CPU: " << buf << " secs";
792837
snprintf( buf, sizeof(buf), "%ld.%06d", stats.ru_stime.tv_sec, stats.ru_stime.tv_usec);
@@ -801,11 +846,13 @@ static void PrintResourceUsage(std::ostream& out) {
801846
cpu_percentage = (cpu_abs / uptime) * 100.0;
802847
out << "\n Average CPU Consumption : "<< cpu_percentage << "%";
803848
out << "\n Maximum resident set size: ";
849+
#if !defined(__MVS__)
804850
WriteInteger(out, stats.ru_maxrss * 1024);
805851
out << " bytes\n Page faults: " << stats.ru_majflt << " (I/O required) "
806852
<< stats.ru_minflt << " (no I/O required)";
807853
out << "\n Filesystem activity: " << stats.ru_inblock << " reads "
808854
<< stats.ru_oublock << " writes";
855+
#endif
809856
}
810857
#ifdef RUSAGE_THREAD
811858
out << "\n\nEvent loop thread resource usage:";
@@ -893,16 +940,16 @@ const static struct {
893940
{"core file size (blocks) ", RLIMIT_CORE},
894941
{"data seg size (kbytes) ", RLIMIT_DATA},
895942
{"file size (blocks) ", RLIMIT_FSIZE},
896-
#if !(defined(_AIX) || defined(__sun))
943+
#if !(defined(_AIX) || defined(__sun) || defined(__MVS__))
897944
{"max locked memory (bytes) ", RLIMIT_MEMLOCK},
898945
#endif
899-
#ifndef __sun
946+
#if !(defined(__sun) || defined(__MVS__))
900947
{"max memory size (kbytes) ", RLIMIT_RSS},
901948
#endif
902949
{"open files ", RLIMIT_NOFILE},
903950
{"stack size (bytes) ", RLIMIT_STACK},
904951
{"cpu time (seconds) ", RLIMIT_CPU},
905-
#ifndef __sun
952+
#if !(defined(__sun) || defined(__MVS__))
906953
{"max user processes ", RLIMIT_NPROC},
907954
#endif
908955
{"virtual memory (kbytes) ", RLIMIT_AS}
@@ -1055,6 +1102,25 @@ static void PrintLoadedLibraries(std::ostream& out, Isolate* isolate) {
10551102
}
10561103
// Release the handle to the process.
10571104
CloseHandle(process_handle);
1105+
1106+
#elif __MVS__
1107+
void *dlcb = 0;
1108+
const int max_path = 1024;
1109+
char buffer[max_path];
1110+
char filename[max_path];
1111+
char *libpath = __getenv("LIBPATH");
1112+
while (dlcb = __dlcb_next(dlcb), dlcb) {
1113+
int len = __dlcb_entry_name(buffer, sizeof(buffer), dlcb);
1114+
void *addr = __dlcb_entry_addr(dlcb);
1115+
if (0 == addr)
1116+
continue;
1117+
if (buffer[0] != '/' && libpath && __find_file_in_path(filename, sizeof(filename), libpath, buffer) > 0) {
1118+
snprintf(buffer + len, sizeof(buffer) - len, " => %s (0x%p)", filename, addr);
1119+
} else
1120+
snprintf(buffer + len, sizeof(buffer) - len, " (0x%p)", addr);
1121+
out << " " << buffer << std::endl;
1122+
}
1123+
out << std::flush;
10581124
#endif
10591125
}
10601126

src/utilities.cc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
#ifdef _AIX
1010
#include <sys/procfs.h> // psinfo_t structure
1111
#endif
12+
#ifdef __MVS__
13+
extern "C" char **__getargv_a(void);
14+
extern "C" int __getargc(void);
15+
extern "C" void *_convert_e2a(void *dst, const void *src, size_t size);
16+
#endif
1217

1318
namespace nodereport {
1419

@@ -278,6 +283,16 @@ void SetCommandLine() {
278283
}
279284
#elif _WIN32
280285
commandline_string = GetCommandLine();
286+
#elif __MVS__
287+
char **argv = __getargv_a();
288+
int argc = __getargc();
289+
290+
commandline_string = "";
291+
std::string separator = "";
292+
for (int i = 0; i < argc; i++) {
293+
commandline_string += separator + argv[i];
294+
separator = " ";
295+
}
281296
#endif
282297
}
283298

@@ -288,6 +303,10 @@ void reportEndpoint(uv_handle_t* h, struct sockaddr* addr, const char* prefix,
288303
std::ostringstream& out) {
289304
uv_getnameinfo_t endpoint;
290305
if (uv_getnameinfo(h->loop, &endpoint, nullptr, addr, NI_NUMERICSERV) == 0) {
306+
#ifdef __MVS__
307+
__e2a_s(endpoint.host);
308+
__e2a_s(endpoint.service);
309+
#endif
291310
out << prefix << endpoint.host << ":" << endpoint.service;
292311
} else {
293312
char host[INET6_ADDRSTRLEN];
@@ -301,6 +320,9 @@ void reportEndpoint(uv_handle_t* h, struct sockaddr* addr, const char* prefix,
301320
const int port = ntohs(family == AF_INET ?
302321
reinterpret_cast<sockaddr_in*>(addr)->sin_port :
303322
reinterpret_cast<sockaddr_in6*>(addr)->sin6_port);
323+
#ifdef __MVS__
324+
__e2a_s(host);
325+
#endif
304326
out << prefix << host << ":" << port;
305327
}
306328
}
@@ -377,7 +399,14 @@ void reportPath(uv_handle_t* h, std::ostringstream& out) {
377399
}
378400
if (rc == 0) {
379401
// buffer is not null terminated.
402+
#ifdef __MVS__
403+
char *tmpbuf = (char*)malloc(size);
404+
_convert_e2a(tmpbuf, buffer, size);
405+
std::string name(tmpbuf, size);
406+
free(tmpbuf);
407+
#else
380408
std::string name(buffer, size);
409+
#endif
381410
out << "filename: " << name;
382411
}
383412
free(buffer);

test/common.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const osMap = {
1010
'linux': 'Linux',
1111
'sunos': 'SunOS',
1212
'win32': 'Windows',
13+
'os390': 'OS/390',
1314
};
1415

1516
const REPORT_SECTIONS = [

0 commit comments

Comments
 (0)