Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement VM timeout #5426

Open
sasq64 opened this issue Apr 25, 2021 · 6 comments
Open

Implement VM timeout #5426

sasq64 opened this issue Apr 25, 2021 · 6 comments

Comments

@sasq64
Copy link
Contributor

sasq64 commented Apr 25, 2021

For non threaded or bare bones environments it would be good to be able to set a timeout for the VM, such that a TimeOut exception is throw after a specified number of milliseconds or opcodes.
Otherwise a simple while true end would require manually killing the process or even reboot.

I will probably patch mrb_vm_exec() for this myself in my project, but I think its something that is useful for others as well.

@dearblue
Copy link
Contributor

I am also interested in this topic.

In the past, I tried to add a pseudo-interrupt feature with polling to the mruby VM, and use that feature to implement Timeout module.
The result worked fine, but the performance of the mruby VM deteriorated by more than 10%, so it's sealed in the closet.

It would be great if it could be ported to various architectures without any performance loss.

@sasq64
Copy link
Contributor Author

sasq64 commented Apr 25, 2021

So I can't come up with a trick that doesn't require to to add an opcode counter and a check & (unlikely) branch, so enabling it will add some overhead, but it should not be as high as 10%.

Where I really need this is for webassembly, where there really is no other way to avoid freezing without it...

@dmajkic
Copy link
Contributor

dmajkic commented Apr 26, 2021

If you enable and set debug hook - you have callback from VM after every opcode.

@sasq64
Copy link
Contributor Author

sasq64 commented Apr 27, 2021

Did this simple test with an opcode_counter, and it works, except mrb->exc is still NULL, so I am probably not
using MRB_THROW() correctly:

diff --git a/src/vm.c b/src/vm.c
index 0665634e..444b3524 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -1061,7 +1061,13 @@ prepare_tagged_break(mrb_state *mrb, uint32_t tag, const struct RProc *proc, mrb
 #ifdef MRB_USE_DEBUG_HOOK
 #define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs));
 #else
-#define CODE_FETCH_HOOK(mrb, irep, pc, regs)
+
+// #define CODE_FETCH_HOOK(mrb, irep, pc, regs)
+#define CODE_FETCH_HOOK(mrb, irep, pc, regs) if(opcode_counter++ == 1000) { \
+  mrb->jmp = prev_jmp; \
+  MRB_THROW(prev_jmp); \
+}
+
 #endif
 
 #ifdef MRB_BYTECODE_DECODE_OPTION
@@ -1156,6 +1162,7 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
   uint16_t b;
   uint16_t c;
   mrb_sym mid;
+  uint32_t opcode_counter = 0;
   const struct mrb_irep_catch_handler *ch;
 
 #ifdef DIRECT_THREADED

@sasq64
Copy link
Contributor Author

sasq64 commented Apr 27, 2021

This worked better;

#define CODE_FETCH_HOOK(mrb, irep, pc, regs) if(opcode_counter++ == 10000) { \
  mrb_raise(mrb, mrb->eException_class, "Timeout"); \
}

@dearblue
Copy link
Contributor

dearblue commented May 2, 2021

If you expand the idea, you can do concurrency processing with a single thread.
ref. #5053

  • Return control to the caller of the mrb_vm_exec() function while preserving the mruby VM stack without raising an exception when the time slice is used up
  • In the caller, switch mrb_state and call the mrb_vm_exec() function
  • When you return to the caller again, switch mrb_state and call the mrb_vm_exec() function.

Regarding concurrency processing, as a constraint of mruby VM, it is not possible to straddle methods by C functions, so the issue is what to do about that.

# The C function can be pseudo-resumed using OP_CALL, so it may not need to call the function directly from the mrb_vm_exec() function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants