Index: trunk/FACT++/src/InterpreterV8.cc
===================================================================
--- trunk/FACT++/src/InterpreterV8.cc	(revision 14636)
+++ trunk/FACT++/src/InterpreterV8.cc	(revision 14637)
@@ -84,24 +84,8 @@
 // ==========================================================================
 
-void InterpreterV8::Terminate()
-{
-    if (!Locker::IsLocked())
-        JsException("***** InterprterV8::Terminate call not locked *****");
-
-    for (auto it=fThreadIds.begin(); it!=fThreadIds.end(); it++)
-        V8::TerminateExecution(*it);
-    fThreadIds.clear();
-
-    if (fThreadId>=0)
-    {
-        V8::TerminateExecution(fThreadId);
-        fThreadId = -1;
-    }
-}
-
 Handle<Value> InterpreterV8::FuncExit(const Arguments &)
 {
-    Terminate();
-    return ThrowException(String::New("exit"));
+    V8::TerminateExecution(fThreadId);
+    return Undefined();
 }
 
@@ -135,12 +119,15 @@
 }
 
-void InterpreterV8::ThreadTimeout(Persistent<Function> func, uint32_t ms)
+void InterpreterV8::ThreadTimeout(int &id, Persistent<Function> func, uint32_t ms)
 {
     const Locker lock;
 
     if (fThreadId<0)
+    {
+        id = -1;
         return;
-
-    const int id = V8::GetCurrentThreadId();
+    }
+
+    id = V8::GetCurrentThreadId();
     fThreadIds.insert(id);
 
@@ -161,9 +148,6 @@
     fThreadIds.erase(id);
 
-    if (!exception.HasCaught())
-        return;
-
-    ReportException(&exception);
-    Terminate();
+    if (!HandleException(exception, "dim.timeout"))
+        V8::TerminateExecution(fThreadId);
 }
 
@@ -190,6 +174,30 @@
     const uint32_t ms = args[0]->Uint32Value();
 
-    fTimeout.push_back(thread(bind(&InterpreterV8::ThreadTimeout, this, func, ms)));
-    return Undefined();
+    int id=-2;
+    fTimeout.push_back(thread(bind(&InterpreterV8::ThreadTimeout, this, ref(id), func, ms)));
+    {
+        const Unlocker unlock;
+        while (id==-2)
+            usleep(1);
+    }
+
+    return Integer::New(id);
+}
+
+Handle<Value> InterpreterV8::FuncKill(const Arguments& args)
+{
+    for (int i=0; i<args.Length(); i++)
+        if (!args[i]->IsInt32())
+            return ThrowException(String::New("All arguments must be int32."));
+
+    uint32_t cnt = 0;
+
+    for (int i=0; i<args.Length(); i++)
+    {
+        V8::TerminateExecution(args[i]->Int32Value());
+        cnt += fThreadIds.erase(args[i]->Int32Value());
+    }
+
+    return Integer::New(cnt);
 }
 
@@ -995,5 +1003,5 @@
     const HandleScope handle_scope;
 
-    Persistent<Object> obj = it->second;
+    Handle<Object> obj = it->second;
 
     obj->CreationContext()->Enter();
@@ -1024,12 +1032,16 @@
     fThreadIds.erase(id);
 
-    if (exception.HasCaught())
-        ReportException(&exception);
+    if (!HandleException(exception, "Service.onchange"))
+        V8::TerminateExecution(fThreadId);
+    //Terminate();
 
     if (ret->IsNativeError())
+    {
         JsException(service+".onchange callback - "+*String::Utf8Value(ret));
-
-    if (ret->IsUndefined() || ret->IsNativeError() || exception.HasCaught())
-        Terminate();
+        V8::TerminateExecution(fThreadId);
+//Terminate();
+    }
+
+    //if (ret->IsUndefined() || ret->IsNativeError()/* || exception.HasCaught()*/)
 }
 
@@ -1097,9 +1109,7 @@
     fThreadIds.erase(id);
 
-    if (!exception.HasCaught())
-        return;
-
-    ReportException(&exception);
-    Terminate();
+    if (!HandleException(exception, "dim.onchange"))
+        V8::TerminateExecution(fThreadId);
+    //Terminate();
 }
 
@@ -1440,19 +1450,18 @@
 // ==========================================================================
 
-bool InterpreterV8::ReportException(TryCatch* try_catch)
-{
-    if (!try_catch->CanContinue())
-        return false;
+bool InterpreterV8::HandleException(TryCatch& try_catch, const char *where)
+{
+    if (!try_catch.HasCaught() || !try_catch.CanContinue())
+        return true;
 
     const HandleScope handle_scope;
 
-    const String::Utf8Value exception(try_catch->Exception());
-
-    if (*exception && string(*exception)=="exit")
+    Handle<Value> except = try_catch.Exception();
+    if (except.IsEmpty() || except->IsNull())
         return true;
-    if (*exception && string(*exception)=="null")
-        return false;
-
-    const Handle<Message> message = try_catch->Message();
+
+    const String::Utf8Value exception(except);
+
+    const Handle<Message> message = try_catch.Message();
     if (message.IsEmpty())
         return false;
@@ -1465,14 +1474,15 @@
         const String::Utf8Value filename(message->GetScriptResourceName());
 
-        if (*filename)
-            out << *filename << ": ";
-        out << "l." << message->GetLineNumber();
+        out << *filename;
+        if (message->GetLineNumber()>0)
+            out << ": l." << message->GetLineNumber();
         if (*exception)
             out << ": ";
     }
 
-    // -------------- SKIP if 'internal' and 'Error' ---------------
     if (*exception)
         out << *exception;
+
+    out << " [" << where << "]";
 
     JsException(out.str());
@@ -1482,5 +1492,4 @@
     if (*sourceline)
         JsException(*sourceline);
-    // -------------- SKIP if 'internal' and 'Error: ' ---------------
 
     // Print wavy underline (GetUnderline is deprecated).
@@ -1495,5 +1504,5 @@
     JsException(out.str());
 
-    const String::Utf8Value stack_trace(try_catch->StackTrace());
+    const String::Utf8Value stack_trace(try_catch.StackTrace());
     if (stack_trace.length()<=0)
         return false;
@@ -1547,11 +1556,20 @@
         JsSetState(3);
 
+    TryCatch exception;
+
     const Handle<Value> result = script->Run();
-    if (result.IsEmpty())
-        return Handle<Value>();
+
+    if (exception.HasCaught())
+    {
+        if (file=="internal")
+            return exception.ReThrow();
+
+        HandleException(exception, "code");
+        return Undefined();
+    }
 
     // If all went well and the result wasn't undefined then print
     // the returned value.
-    if (!result->IsUndefined())
+    if (!result.IsEmpty() && result->IsUndefined())
         JsResult(*String::Utf8Value(result));
 
@@ -1596,5 +1614,5 @@
 
 
-void InterpreterV8::AddFormatToGlobal() const
+void InterpreterV8::AddFormatToGlobal()// const
 {
     const string code =
@@ -1651,4 +1669,6 @@
         "}"*/;
 
+    // ExcuteInternal does not work properly here...
+    // If suring compilation an exception is thrown, it will not work
     Handle<Script> script = Script::New(String::New(code.c_str()), String::New("internal"));
     if (!script.IsEmpty())
@@ -1683,6 +1703,15 @@
     dim->Set(String::New("sleep"),     FunctionTemplate::New(WrapSleep),     ReadOnly);
     dim->Set(String::New("timeout"),   FunctionTemplate::New(WrapTimeout),   ReadOnly);
+    dim->Set(String::New("kill"),      FunctionTemplate::New(WrapKill),      ReadOnly);
     dim->Set(String::New("subscribe"), FunctionTemplate::New(WrapSubscribe), ReadOnly);
     dim->Set(String::New("file"),      FunctionTemplate::New(WrapFile),      ReadOnly);
+
+    // timeout   -> Thread  - class?
+    // subscribe -> Service - class?
+    // file      -> File    - class?
+    // new class State ?
+    // newState -> return State?
+    // setState -> return State?
+    // getState -> return State?
 
     Handle<ObjectTemplate> onchange = ObjectTemplate::New();
@@ -1728,4 +1757,7 @@
     }
 
+    // Switch off eval(). It is not possible to track it's exceptions.
+    context->AllowCodeGenerationFromStrings(false);
+
     Context::Scope scope(context);
 
@@ -1738,21 +1770,28 @@
     //V8::ResumeProfiler();
 
+    bool rc;
+
+    TryCatch exception;
+
     AddFormatToGlobal();
 
-    JsStart(filename);
-
-    //context->Enter();
-
-    TryCatch exception;
-
-    Locker::StartPreemption(10);
-    bool rc = ExecuteFile(filename, true);
-
-    Locker::StopPreemption();
-
-    Terminate();
-
-    if (exception.HasCaught())
-        rc = ReportException(&exception);
+    if (!exception.HasCaught())
+    {
+        JsStart(filename);
+
+        Locker::StartPreemption(10);
+
+        rc = ExecuteFile(filename, true);
+
+        Locker::StopPreemption();
+
+        // Stop all other threads
+        for (auto it=fThreadIds.begin(); it!=fThreadIds.end(); it++)
+            V8::TerminateExecution(*it);
+        fThreadIds.clear();
+    }
+
+    // Handle an exception
+    rc = HandleException(exception, "main");
 
     // IsProfilerPaused()
@@ -1773,8 +1812,7 @@
     //context->Exit();
 
-    // Thre threads are started already and wait to get the lock
-    // So we have to unlock (manual preemtion) so they they get
-    // the signal to terminate. After they are all successfully
-    // terminated, just to be sure... we lock again
+    // The threads are started already and wait to get the lock
+    // So we have to unlock (manual preemtion) so that they get
+    // the signal to terminate.
     {
         const Unlocker unlock;
@@ -1814,5 +1852,6 @@
 {
     Locker locker;
-    This->Terminate();
+    V8::TerminateExecution(This->fThreadId);
+    //This->Terminate();
 }
 
Index: trunk/FACT++/src/InterpreterV8.h
===================================================================
--- trunk/FACT++/src/InterpreterV8.h	(revision 14636)
+++ trunk/FACT++/src/InterpreterV8.h	(revision 14637)
@@ -50,12 +50,10 @@
 
 #ifdef HAVE_V8
-    void Terminate();
-
-    bool ReportException(v8::TryCatch* try_catch);
+    bool HandleException(v8::TryCatch &try_catch, const char *where);
     bool ExecuteFile(const std::string &name, bool main=false);
     v8::Handle<v8::Value> ExecuteCode(const std::string &code, const std::string &file="internal", bool main=false);
     v8::Handle<v8::Value> ExecuteInternal(const std::string &code);
 
-    void ThreadTimeout(v8::Persistent<v8::Function> func, uint32_t ms);
+    void ThreadTimeout(int &id, v8::Persistent<v8::Function> func, uint32_t ms);
 
     v8::Handle<v8::Value> FuncWait(const v8::Arguments& args);
@@ -63,4 +61,5 @@
     v8::Handle<v8::Value> FuncSleep(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncTimeout(const v8::Arguments& args);
+    v8::Handle<v8::Value> FuncKill(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncPrint(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncAlarm(const v8::Arguments& args);
@@ -108,4 +107,5 @@
     static v8::Handle<v8::Value> WrapSleep(const v8::Arguments &args)    { if (This) return This->FuncSleep(args);    else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapTimeout(const v8::Arguments &args)  { if (This) return This->FuncTimeout(args);  else return v8::Undefined(); }
+    static v8::Handle<v8::Value> WrapKill(const v8::Arguments &args)     { if (This) return This->FuncKill(args);     else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapExit(const v8::Arguments &args)     { if (This) return This->FuncExit(args);     else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapState(const v8::Arguments &args)    { if (This) return This->FuncState(args);    else return v8::Undefined(); }
@@ -178,5 +178,5 @@
     void JsHandleState(const std::string &, const State &);
 
-    void AddFormatToGlobal() const;
+    void AddFormatToGlobal();
 
     bool JsRun(const std::string &, const std::map<std::string,std::string> & = std::map<std::string,std::string>());
