kuroko/tools/watchdog.c
2024-03-07 07:23:21 +09:00

100 lines
2.2 KiB
C

#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <kuroko/kuroko.h>
#include <kuroko/vm.h>
#include <kuroko/debug.h>
#include <kuroko/util.h>
#include "common.h"
#define DEFAULT_LIMIT 500000
static int usage(char * argv[]) {
fprintf(stderr, "usage: %s [-s COUNT] [-q] FILE [args...]\n", argv[0]);
return 1;
}
static int help(char * argv[]) {
usage(argv);
fprintf(stderr,
"Run scripts with an instruction counter and halt when a "
"limit is exceeded. The default limit is %d. A total count of "
"executed instructions is printed after completion.\n"
"\n"
"Options:\n"
" -s COUNT Set watchdog timeout to COUNT instructions.\n"
" Specify -1 to set disable limit.\n"
" -q Do not print total instruction count.\n"
"\n"
" --help Show this help text.\n"
"\n",
DEFAULT_LIMIT);
return 0;
}
static size_t instrCounter = 0; /* Total counter of executed instructions */
static size_t stopAt = DEFAULT_LIMIT;
static int quiet = 0;
int krk_callgrind_debuggerHook(KrkCallFrame * frame) {
instrCounter++;
if (instrCounter < stopAt) return KRK_DEBUGGER_STEP;
if (instrCounter == stopAt) {
krk_runtimeError(vm.exceptions->baseException, "Watchdog counter expired.");
}
return KRK_DEBUGGER_CONTINUE;
}
int main(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "+:s:q-:")) != -1) {
switch (opt) {
case 's':
stopAt = strtoul(optarg,NULL,10);
break;
case 'q':
quiet = 1;
break;
case '?':
if (optopt != '-') {
fprintf(stderr, "%s: unrocognized option '%c'\n", argv[0], optopt);
return 1;
}
optarg = argv[optind]+1;
/* fall through */
case '-':
if (!strcmp(optarg,"help")) {
return help(argv);
} else {
fprintf(stderr, "%s: unrecognized option: '--%s'\n", argv[0], optarg);
return 1;
}
}
}
if (optind == argc) {
return usage(argv);
}
findInterpreter(argv);
krk_initVM(KRK_THREAD_SINGLE_STEP);
krk_debug_registerCallback(krk_callgrind_debuggerHook);
addArgs(argc,argv);
krk_startModule("__main__");
krk_runfile(argv[optind],argv[optind]);
if (!quiet) {
fprintf(stderr, "%zu total instructions\n", instrCounter);
}
krk_freeVM();
return 0;
}