Skip to content

Commit

Permalink
Implemented using MVM_exepath.
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickbkr authored and PatZim committed Mar 20, 2019
1 parent ed9b963 commit 7ab1981
Show file tree
Hide file tree
Showing 3 changed files with 252 additions and 319 deletions.
250 changes: 250 additions & 0 deletions src/vm/moar/runner/main.c
@@ -0,0 +1,250 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
#include <moar.h>

#ifndef _WIN32
# include <libgen.h>
#endif

#ifndef _WIN32
# include "signal.h"
#endif

#ifndef _WIN32
# include <unistd.h>
#else
# include <process.h>
#endif

#if defined(_MSC_VER)
#define strtoll _strtoi64
#endif

/* flags need to be sorted alphabetically */

enum {
NOT_A_FLAG = -2,
UNKNOWN_FLAG = -1,

FLAG_SUSPEND,
FLAG_DUMP,
FLAG_TRACING,

OPT_DEBUGPORT
};

static const char *const FLAGS[] = {
"--debug-suspend",
"--dump",
"--full-cleanup",
"--tracing",
};

static int cmp_flag(const void *key, const void *value)
{
return strcmp(key, *(char **)value);
}

static int starts_with(const char *str, const char *want) {
size_t str_len = strlen(str);
size_t want_len = strlen(want);
return str_len < want_len
? 0
: strncmp(str, want, want_len) == 0;
}

static int parse_flag(const char *arg)
{
const char *const *found;

if (!arg || arg[0] != '-')
return NOT_A_FLAG;

found = bsearch(arg, FLAGS, sizeof FLAGS / sizeof *FLAGS, sizeof *FLAGS, cmp_flag);

if (found)
return (int)(found - FLAGS);
else if (starts_with(arg, "--debug-port="))
return OPT_DEBUGPORT;
else
return UNKNOWN_FLAG;
}

#ifndef _WIN32
int main(int argc, char *argv[])
#else
int wmain(int argc, wchar_t *wargv[])
#endif
{
MVMInstance *instance;
int res;
char *input_file;
char *exec_path;
size_t exec_path_size;
int dir_path_size;
char *lib_path[3];

#ifdef _WIN32
char **argv = MVM_UnicodeToUTF8_argv(argc, wargv);
#endif

int dump = 0;
int argi = 1;
int flag;
int new_argc = 0;

unsigned int interval_id;
char telemeh_inited = 0;

MVMuint32 debugserverport = 0;
int start_suspended = 0;

for (; (flag = parse_flag(argv[argi])) != NOT_A_FLAG; ++argi) {
switch (flag) {
case FLAG_DUMP:
dump = 1;
continue;

#if MVM_TRACING
case FLAG_TRACING:
MVM_interp_enable_tracing();
continue;
#endif

case FLAG_SUSPEND:
start_suspended = 1;
continue;

case OPT_DEBUGPORT: {
MVMint64 port;
char *portstr = argv[argi] + strlen("--debugport=") + 1;
char *endptr;
port = strtoll(portstr, &endptr, 10);
if (*endptr != '\0') {
fprintf(stderr, "ERROR: Invalid characters in debug port flag: %s\n", portstr);
return EXIT_FAILURE;
}
if (port <= 1024 || 65535 < port) {
fprintf(stderr, "ERROR: debug server port out of range. We only accept ports above 1024 and below 65535. (got: %"PRIi64")\n", port);
return EXIT_FAILURE;
}
debugserverport = (MVMuint32)port;
break;
}

default:
argv[new_argc++] = argv[argi];
}
}

for (; argv[argi]; ++argi) {
argv[new_argc++] = argv[argi];
}


#ifdef HAVE_TELEMEH
if (getenv("MVM_TELEMETRY_LOG")) {
char path[256];
FILE *fp;
snprintf(path, 255, "%s.%d", getenv("MVM_TELEMETRY_LOG"),
#ifdef _WIN32
_getpid()
#else
getpid()
#endif
);
fp = fopen(path, "w");
if (fp) {
MVM_telemetry_init(fp);
telemeh_inited = 1;
interval_id = MVM_telemetry_interval_start(0, "moarvm startup");
}
}
#endif

exec_path_size = 4096;
exec_path = (char*)malloc(exec_path_size);
res = MVM_exepath(exec_path, &exec_path_size);
while (res < 0 && exec_path_size < 4096*8) {
exec_path_size *= 2;
exec_path = (char*)realloc(exec_path, exec_path_size);
res = MVM_exepath(exec_path, &exec_path_size);
}
if (res < 0) {
fprintf(stderr, "ERROR: Could not retrieve executable path.\n");
return EXIT_FAILURE;
}

#ifdef _WIN32
PathRemoveFileSpecA(exec_path);
#else
exec_path = dirname(exec_path);
#endif

dir_path_size = strlen(exec_path);

lib_path[0] = (char*)malloc(dir_path_size + 50);
lib_path[1] = (char*)malloc(dir_path_size + 50);
lib_path[2] = (char*)malloc(dir_path_size + 50);
input_file = (char*)malloc(dir_path_size + 50);

memcpy(lib_path[0], exec_path, dir_path_size);
memcpy(lib_path[1], exec_path, dir_path_size);
memcpy(lib_path[2], exec_path, dir_path_size);
memcpy(input_file, exec_path, dir_path_size);

free(exec_path);

#ifdef _WIN32
strcpy(lib_path[0] + dir_path_size, "\\..\\share\\nqp\\lib");
strcpy(lib_path[1] + dir_path_size, "\\..\\share\\perl6\\lib");
strcpy(lib_path[2] + dir_path_size, "\\..\\share\\perl6\\runtime");
strcpy(input_file + dir_path_size, "\\..\\share\\perl6\\runtime\\perl6.moarvm");
#else
strcpy(lib_path[0] + dir_path_size, "/../share/nqp/lib");
strcpy(lib_path[1] + dir_path_size, "/../share/perl6/lib");
strcpy(lib_path[2] + dir_path_size, "/../share/perl6/runtime");
strcpy(input_file + dir_path_size, "/../share/perl6/runtime/perl6.moarvm");
#endif

instance = MVM_vm_create_instance();

/* stash the rest of the raw command line args in the instance */
MVM_vm_set_clargs(instance, new_argc, argv);
MVM_vm_set_prog_name(instance, input_file);
MVM_vm_set_lib_path(instance, 3, (const char **)lib_path);

/* Ignore SIGPIPE by default, since we error-check reads/writes. This does
* not prevent users from setting up their own signal handler for SIGPIPE,
* which will take precedence over this ignore. */
#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif

if (debugserverport > 0) {
MVM_debugserver_init(instance->main_thread, debugserverport);

if (start_suspended) {
instance->main_thread->gc_status = MVMGCStatus_INTERRUPT | MVMSuspendState_SUSPEND_REQUEST;
}
}

if (dump) MVM_vm_dump_file(instance, input_file);
else MVM_vm_run_file(instance, input_file);

#ifdef HAVE_TELEMEH
if (getenv("MVM_TELEMETRY_LOG") && telemeh_inited) {
MVM_telemetry_interval_stop(0, interval_id, "moarvm teardown");
MVM_telemetry_finish();
}
#endif

MVM_vm_exit(instance);

free(lib_path[0]);
free(lib_path[1]);
free(lib_path[2]);
free(input_file);
}
4 changes: 2 additions & 2 deletions tools/build/Makefile-Moar.in
Expand Up @@ -216,12 +216,12 @@ $(M_VALGRIND_RUNNER): tools/build/create-moar-runner.p6 $(PERL6_MOAR) $(SETTING_
$(M_RUN_PERL6) tools/build/create-moar-runner.p6 "$(MOAR)" perl6.moarvm perl6-valgrind-m . "valgrind" --nqp-lib=blib norelocatable . blib "$(M_LIBPATH)"
-$(CHMOD) 755 $(M_VALGRIND_RUNNER)

$(M_C_RUNNER): tools/build/moar-runner.c
$(M_C_RUNNER): src/vm/moar/runner/main.c
$(RM_F) $(M_C_RUNNER)
# Using only the pkgconfig moar includes does not work, because moar.h assumes all the specific includes below.
$(M_CC) @moar::ccshared@ $(M_CFLAGS) $(M_LDFLAGS) -I$(M_INCPATH) -I$(M_INCPATH)/moar \
-I$(M_INCPATH)/libatomic_ops -I$(M_INCPATH)/dyncall -I$(M_INCPATH)/moar -I$(M_INCPATH)/sha1 -I$(M_INCPATH)/tinymt -I$(M_INCPATH)/libtommath -I$(M_INCPATH)/libuv \
-L@moar::libdir@ -Wl,-z,origin,-rpath,'$$ORIGIN/../lib' -lmoar @moar::ccout@$@ tools/build/moar-runner.c
-L@moar::libdir@ -Wl,-z,origin,-rpath,'$$ORIGIN/../lib' -lmoar @moar::ccout@$@ src/vm/moar/runner/main.c


## testing targets
Expand Down

0 comments on commit 7ab1981

Please sign in to comment.