Skip to content

Commit

Permalink
feat: Added support for Signal handling
Browse files Browse the repository at this point in the history
  • Loading branch information
jacopodl committed May 7, 2024
1 parent edf234f commit a6bd5ac
Show file tree
Hide file tree
Showing 8 changed files with 404 additions and 7 deletions.
4 changes: 4 additions & 0 deletions argon/vm/argon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <argon/vm/config.h>
#include <argon/vm/runtime.h>
#include <argon/vm/signal.h>

#include <argon/vm/argon.h>

Expand Down Expand Up @@ -89,6 +90,9 @@ int argon::vm::ArgonMain(int argc, char **argv) {
if ((context = ContextNew(&config)) == nullptr)
return EXIT_FAILURE;

if(!SignalInit(context))
return EXIT_FAILURE;

if (!SetupImportPaths(context->imp))
return EXIT_FAILURE;

Expand Down
1 change: 1 addition & 0 deletions argon/vm/importer/import.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ ARGON_FUNCTION(import_builtins_locator, builtins_locator,
argon::vm::mod::module_limits_,
argon::vm::mod::module_os_,
argon::vm::mod::module_runtime_,
argon::vm::mod::module_signal_,
argon::vm::mod::module_socket_
};
ImportSpec *spec = nullptr;
Expand Down
1 change: 1 addition & 0 deletions argon/vm/mod/modules.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace argon::vm::mod {
extern const datatype::ModuleInit *module_limits_;
extern const datatype::ModuleInit *module_os_;
extern const datatype::ModuleInit *module_runtime_;
extern const datatype::ModuleInit *module_signal_;
extern const datatype::ModuleInit *module_socket_;

} // namespace argon::vm::mod
Expand Down
226 changes: 226 additions & 0 deletions argon/vm/mod/signal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
// This source file is part of the Argon project.
//
// Licensed under the Apache License v2.0

#include <csignal>

#include <argon/vm/signal.h>

#include <argon/vm/datatype/error.h>
#include <argon/vm/datatype/function.h>
#include <argon/vm/datatype/integer.h>
#include <argon/vm/datatype/module.h>
#include <argon/vm/datatype/nil.h>

#include <argon/vm/mod/modules.h>

using namespace argon::vm::datatype;

ARGON_FUNCTION(signal_signal, signal,
"Set the signal handler for the specified signal number to the given handler function.\n"
"\n"
"- Parameters:\n"
" - signum: Signal number to set the handler for.\n"
" - handler: Function to be called when the signal is received.\n",
"i: signum, Fn: handler", false, false) {
auto signum = (int) ((Integer *) args[0])->sint;
auto *func = (Function *) args[1];

if (signum < 0) {
ErrorFormat(kValueError[0], "signum cannot be less than zero");
return nullptr;
}

if (!IsNull((ArObject *) func)) {
auto arity = func->arity;
if (func->currying != nullptr)
arity -= func->currying->length;

if (arity != 1) {
ErrorFormat(kValueError[0], "expected a handler that only accepts one parameter");
return nullptr;
}

if (func->IsGenerator()) {
ErrorFormat(kTypeError[0], kTypeError[7], "signal", ARGON_RAW_STRING(func->qname));
return nullptr;
}
}

if (!argon::vm::SignalAddHandler(signum, func)) {
ErrorFormat(kValueError[0], "unknown signal %d", signum);
return nullptr;
}

return (ArObject *) IncRef(Nil);
}

ARGON_FUNCTION(signal_reset, reset,
"Remove all signal handlers that have been set previously.\n"
"\n",
nullptr, false, false) {
argon::vm::SignalResetHandlers();

return (ArObject *) IncRef(Nil);
}

bool SignalInit(Module *self) {
#define AddIntConstant(c) \
if(!ModuleAddIntConstant(self, #c, c)) \
return false

#ifdef SIGHUP
AddIntConstant(SIGHUP);
#endif

#ifdef SIGINT
AddIntConstant(SIGINT);
#endif

#ifdef SIGQUIT
AddIntConstant(SIGQUIT);
#endif

#ifdef SIGILL
AddIntConstant(SIGILL);
#endif

#ifdef SIGTRAP
AddIntConstant(SIGTRAP);
#endif

#ifdef SIGABRT
AddIntConstant(SIGABRT);
#endif

#ifdef SIGIOT
AddIntConstant(SIGIOT);
#endif

#ifdef SIGBUS
AddIntConstant(SIGBUS);
#endif

#ifdef SIGFPE
AddIntConstant(SIGFPE);
#endif

#ifdef SIGKILL
AddIntConstant(SIGKILL);
#endif

#ifdef SIGUSR1
AddIntConstant(SIGUSR1);
#endif

#ifdef SIGSEGV
AddIntConstant(SIGSEGV);
#endif

#ifdef SIGUSR2
AddIntConstant(SIGUSR2);
#endif

#ifdef SIGPIPE
AddIntConstant(SIGPIPE);
#endif

#ifdef SIGALRM
AddIntConstant(SIGALRM);
#endif

#ifdef SIGTERM
AddIntConstant(SIGTERM);
#endif

#ifdef SIGSTKFLT
AddIntConstant(SIGSTKFLT);
#endif

#ifdef SIGCHLD
AddIntConstant(SIGCHLD);
#endif

#ifdef SIGCONT
AddIntConstant(SIGCONT);
#endif

#ifdef SIGSTOP
AddIntConstant(SIGSTOP);
#endif

#ifdef SIGTSTP
AddIntConstant(SIGTSTP);
#endif

#ifdef SIGTTIN
AddIntConstant(SIGTTIN);
#endif

#ifdef SIGTTOU
AddIntConstant(SIGTTOU);
#endif

#ifdef SIGURG
AddIntConstant(SIGURG);
#endif

#ifdef SIGXCPU
AddIntConstant(SIGXCPU);
#endif

#ifdef SIGXFSZ
AddIntConstant(SIGXFSZ);
#endif

#ifdef SIGVTALRM
AddIntConstant(SIGVTALRM);
#endif

#ifdef SIGPROF
AddIntConstant(SIGPROF);
#endif

#ifdef SIGWINCH
AddIntConstant(SIGWINCH);
#endif

#ifdef SIGIO
AddIntConstant(SIGIO);
#endif

#ifdef SIGPOLL
AddIntConstant(SIGPOLL);
#endif

#ifdef SIGPWR
AddIntConstant(SIGPWR);
#endif

#ifdef SIGSYS
AddIntConstant(SIGSYS);
#endif

#ifdef SIGUNUSED
AddIntConstant(SIGUNUSED);
#endif

return true;
#undef AddIntConstant
}

const ModuleEntry signal_entries[] = {
MODULE_EXPORT_FUNCTION(signal_signal),
MODULE_EXPORT_FUNCTION(signal_reset),
ARGON_MODULE_SENTINEL
};

constexpr ModuleInit ModuleSignal = {
"signal",
"This module provides mechanisms to use signal handlers in Argon.",
nullptr,
signal_entries,
SignalInit,
nullptr
};
const ModuleInit *argon::vm::mod::module_signal_ = &ModuleSignal;
12 changes: 6 additions & 6 deletions argon/vm/runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <argon/vm/fiber.h>
#include <argon/vm/fqueue.h>
#include <argon/vm/runtime.h>
#include <argon/vm/signal.h>
#include <argon/vm/traceback.h>

using namespace argon::vm;
Expand Down Expand Up @@ -658,12 +659,9 @@ ArObject *argon::vm::GetLastError() {
return error;
}

Future *argon::vm::EvalAsync(Function *func, ArObject **argv, ArSize argc, OpCodeCallMode mode) {
Fiber *fiber;

assert(ost_local != nullptr);

fiber = AllocFiber(GetFiber()->context);
Future *argon::vm::EvalAsync(Context *context, datatype::Function *func, datatype::ArObject **argv,
datatype::ArSize argc, argon::vm::OpCodeCallMode mode) {
auto *fiber = AllocFiber(context);
if (fiber == nullptr)
return nullptr;

Expand Down Expand Up @@ -885,6 +883,8 @@ bool argon::vm::Initialize(const Config *config) {
if (!loop2::EvLoopInitRun())
return false;

SignalProcMask();

// TODO: panic_oom

return true;
Expand Down
7 changes: 6 additions & 1 deletion argon/vm/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace argon::vm {

argon::vm::datatype::ArObject *GetLastError();

argon::vm::datatype::Future *EvalAsync(datatype::Function *func, datatype::ArObject **argv,
argon::vm::datatype::Future *EvalAsync(Context *context, datatype::Function *func, datatype::ArObject **argv,
datatype::ArSize argc, OpCodeCallMode mode);

argon::vm::datatype::Result *Eval(Context *context, datatype::Code *code, datatype::Namespace *ns);
Expand Down Expand Up @@ -64,6 +64,11 @@ namespace argon::vm {

Fiber *GetFiber();

inline argon::vm::datatype::Future *EvalAsync(datatype::Function *func, datatype::ArObject **argv,
datatype::ArSize argc, OpCodeCallMode mode) {
return EvalAsync(GetFiber()->context, func, argv, argc, mode);
}

FiberStatus GetFiberStatus();

Frame *GetFrame();
Expand Down
Loading

0 comments on commit a6bd5ac

Please sign in to comment.