feat(library/vm): check heartbeat in function calls

This commit is contained in:
Leonardo de Moura 2017-02-12 12:29:32 -08:00
parent 80ac700e36
commit 1306e56381
6 changed files with 33 additions and 13 deletions

View file

@ -3111,6 +3111,7 @@ void vm_state::run() {
}
case opcode::InvokeGlobal: {
check_interrupted();
check_heartbeat();
check_memory("vm");
/**
Instruction: ginvoke fn
@ -3145,6 +3146,7 @@ void vm_state::run() {
}
case opcode::InvokeBuiltin: {
check_interrupted();
check_heartbeat();
check_memory("vm");
/**
Instruction: builtin fn
@ -3166,6 +3168,7 @@ void vm_state::run() {
}
case opcode::InvokeCFun: {
check_interrupted();
check_heartbeat();
check_memory("vm");
/**
Instruction: cfun fn

View file

@ -55,10 +55,6 @@ char const * memory_exception::what() const noexcept {
}
char const * heartbeat_exception::what() const noexcept {
std::string & buffer = get_g_buffer();
std::ostringstream s;
s << "(deterministic) timeout detected at '" << m_component_name << "' (potential solution: increase timeout threshold)";
buffer = s.str();
return buffer.c_str();
return "(deterministic) timeout";
}
}

View file

@ -87,11 +87,10 @@ public:
};
class heartbeat_exception : public throwable {
std::string m_component_name;
public:
heartbeat_exception(char const * component_name):m_component_name(component_name) {}
heartbeat_exception() {}
virtual char const * what() const noexcept;
virtual throwable * clone() const { return new heartbeat_exception(m_component_name.c_str()); }
virtual throwable * clone() const { return new heartbeat_exception(); }
virtual void rethrow() const { throw *this; }
};
}

View file

@ -27,9 +27,10 @@ void set_max_heartbeat_thousands(unsigned max) { g_max_heartbeat = static_cast<s
scope_heartbeat::scope_heartbeat(size_t max):flet<size_t>(g_heartbeat, max) {}
scope_max_heartbeat::scope_max_heartbeat(size_t max):flet<size_t>(g_max_heartbeat, max) {}
static void check_heartbeat(char const * component_name) {
void check_heartbeat() {
inc_heartbeat();
if (g_max_heartbeat > 0 && g_heartbeat > g_max_heartbeat)
throw heartbeat_exception(component_name);
throw heartbeat_exception();
}
MK_THREAD_LOCAL_GET(atomic_bool, get_g_interrupt, false);
@ -54,11 +55,10 @@ void check_interrupted() {
}
void check_system(char const * component_name) {
inc_heartbeat();
check_stack(component_name);
check_memory(component_name);
check_interrupted();
check_heartbeat(component_name);
check_heartbeat();
}
void sleep_for(unsigned ms, unsigned step_ms) {

View file

@ -40,7 +40,7 @@ public:
scope_max_heartbeat(size_t max);
};
void init_thread_max_heartbeat();
void check_heartbeat();
atomic_bool * get_interrupt_flag();

View file

@ -0,0 +1,22 @@
meta def f : nat → nat
| n := f (n + 1)
vm_eval try_for 100 (f 10)
vm_eval try_for 1000 (f 10)
meta def mk : nat → list nat
| 0 := []
| (n+1) := n :: mk n
example : true :=
begin
tactic.fail_if_success (guard(to_bool (try_for 1 ((mk 1000)^.length) = some 1000))),
constructor
end
example : true :=
begin
guard (try_for 100 ((mk 1000)^.length) = some 1000),
constructor
end