Index: /trunk/FACT++/src/InterpreterV8.cc
===================================================================
--- /trunk/FACT++/src/InterpreterV8.cc	(revision 15072)
+++ /trunk/FACT++/src/InterpreterV8.cc	(revision 15073)
@@ -34,4 +34,5 @@
 v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateSky;
 v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateEvent;
+v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateDescription;
 //v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateDatabase;
 
@@ -129,4 +130,58 @@
 }
 
+Handle<Value> InterpreterV8::FuncTimeout(const Arguments &args)
+{
+    if (args.Length()<2)
+        return ThrowException(String::New("Number of arguments must be at least two."));
+
+    if (!args[0]->IsNull() && !args[0]->IsInt32())
+        return ThrowException(String::New("Argument 0 not null and not an int32."));
+
+    if (!args[1]->IsFunction())
+        return ThrowException(String::New("Argument 1 not a function."));
+
+    const int32_t timeout = args[0]->IsNull() ? 0 : args[0]->Int32Value();
+    const bool    null    = args[0]->IsNull();
+
+    HandleScope handle_scope;
+
+    TryCatch exception;
+
+    const Handle<Script> sleep = Script::Compile(String::New("v8.sleep();"), String::New("internal"));
+    if (sleep.IsEmpty())
+        return Undefined();
+
+    Handle<Function> func = Handle<Function>::Cast(args[1]);
+
+    Handle<Value> argv[args.Length()-2];
+    for (int i=0; i<args.Length()-2; i++)
+        argv[i] = args[i+2];
+
+    Time t;
+    while (!exception.HasCaught())
+    {
+        const Handle<Value> rc = func->Call(func, args.Length()-2, argv);
+        if (!rc->IsUndefined())
+            return rc;
+
+        if (!null && Time()-t>=boost::posix_time::milliseconds(abs(timeout)))
+            break;
+
+        // We cannot sleep directly because we have to give control back to
+        // JavaScript ever now and then. This also allows us to catch
+        // exceptions, either from the preemption or ConvertEvent
+        sleep->Run();
+    }
+
+    if (exception.HasCaught())
+        return exception.ReThrow();
+
+    if (timeout<0)
+        return Undefined();
+
+    const string str = "Waiting for func to return a defined value timed out.";
+    return ThrowException(String::New(str.c_str()));
+}
+
 void InterpreterV8::Thread(int &id, Persistent<Function> func, uint32_t ms)
 {
@@ -139,6 +194,12 @@
     }
 
-    id = V8::GetCurrentThreadId();
-    fThreadIds.insert(id);
+    // Warning: As soon as id is set, the parent of this thread might terminate
+    //          and hance the reference to id does not exist anymore. So, id
+    //          is just a kind of return value and must not be used at all
+    //          otherwise.
+
+    const int id_local = V8::GetCurrentThreadId();
+    id = id_local;
+    fThreadIds.insert(id_local);
 
     const HandleScope handle_scope;
@@ -153,5 +214,5 @@
 
     func.Dispose();
-    fThreadIds.erase(id);
+    fThreadIds.erase(id_local);
 
     if (!HandleException(exception, "thread"))
@@ -485,7 +546,10 @@
             break;
 
+    if (is==services.end())
+        return Undefined();
+
     HandleScope handle_scope;
 
-    Handle<Array> arr = Array::New();
+    Handle<Object> arr = fTemplateDescription->GetFunction()->NewInstance();//Object::New();
     if (arr.IsEmpty())
         return Undefined();
@@ -511,5 +575,6 @@
             return Undefined();
 
-        obj->Set(String::New("name"), String::New(it->name.c_str()), ReadOnly);
+        if (!it->name.empty())
+            obj->Set(String::New("name"), String::New(it->name.c_str()), ReadOnly);
         if (!it->comment.empty())
             obj->Set(String::New("description"), String::New(it->comment.c_str()), ReadOnly);
@@ -628,5 +693,9 @@
             return ThrowException(String::New("File name missing"));
 
-        if (!ExecuteFile(*file))
+        TryCatch exception;
+        const bool rc = ExecuteFile(*file);
+        if (exception.HasCaught())
+            HandleException(exception, "include");
+        if (!rc)
         {
             V8::TerminateExecution(fThreadId);
@@ -1145,5 +1214,5 @@
         return Undefined();
 
-    //const Handle<String> data   = String::New("data");
+    const Handle<String> data   = String::New("data");
     const Handle<String> object = String::New("obj");
 
@@ -1168,14 +1237,23 @@
             {
                 if (!named)
-                    return handle_scope.Close(val);
-
-                const Handle<Object> event = val->ToObject();
-                const Handle<Value>  obj   = event->Get(object);
-
-                if (!obj.IsEmpty() && obj->IsObject())
                 {
-                    // Has names and data was received?
-                    if (obj->ToObject()->GetOwnPropertyNames()->Length()>0)
+                    const Handle<Object> event = val->ToObject();
+                    const Handle<Value>  obj   = event->Get(data);
+
+                    // No names (no 'obj'), but 'data'
+                    if (!obj.IsEmpty() && !obj->IsUndefined())
                         return handle_scope.Close(val);
+                }
+                else
+                {
+                    const Handle<Object> event = val->ToObject();
+                    const Handle<Value>  obj   = event->Get(object);
+
+                    if (!obj.IsEmpty() && obj->IsObject())
+                    {
+                        // Has names and data was received?
+                        if (obj->ToObject()->GetOwnPropertyNames()->Length()>0)
+                            return handle_scope.Close(val);
+                    }
                 }
             }
@@ -1873,4 +1951,5 @@
 
     // maybe skip: "    at internal:"
+    // maybe skip: "    at unknown source:"
 
     auto it = tokenizer.begin();
@@ -1915,5 +1994,4 @@
 
     const Handle<Value> result = script->Run();
-
     if (exception.HasCaught())
     {
@@ -1957,4 +2035,13 @@
 bool InterpreterV8::ExecuteConsole()
 {
+    // Just necessray for the Handle<Script>
+    const HandleScope handle_scope;
+
+    // A void script doing nothing than making sure that some JavaScript is executed
+    const Handle<Script> catcher = Script::Compile(String::New(";"), String::New(""));
+
+    // Unlocking is necessary for the preemption to work
+    const Unlocker global_unlock;
+
     JsSetState(3);
 
@@ -1965,5 +2052,4 @@
 
     string command;
-
     while (1)
     {
@@ -1990,9 +2076,22 @@
         }
 
+        // Locking is necessary to be able to execute java script code
+        const Locker lock;
+
+        // Dump all pending exceptions. This is mainly to catch the 'null' exception
+        // thrown if a running JavaScript should be terminated from somewhere.
+        while (1)
+        {
+            TryCatch exception;
+            catcher->Run();
+            if (!exception.HasCaught())
+                break;
+        }
+
         // Catch exceptions during code compilation
         TryCatch exception;
 
         // Execute code which was entered
-        bool rc = ExecuteCode(command, "", false).IsEmpty();
+        bool rc = ExecuteCode(command, "console", false).IsEmpty();
         if (exception.HasCaught())
         {
@@ -2000,4 +2099,15 @@
             rc = true;
         }
+
+        // Stop all other threads
+        for (auto it=fThreadIds.begin(); it!=fThreadIds.end(); it++)
+            V8::TerminateExecution(*it);
+
+        // Allow the java scripts (threads) to run and hence to terminate
+        const Unlocker unlock;
+
+        // Wait until all threads are terminated
+        while (fThreadIds.size()>0)
+            usleep(1000);
 
         // In case of an exception add an empty line to the output
@@ -2145,4 +2255,5 @@
     Handle<ObjectTemplate> v8 = ObjectTemplate::New();
     v8->Set(String::New("sleep"),   FunctionTemplate::New(WrapSleep), ReadOnly);
+    v8->Set(String::New("timeout"), FunctionTemplate::New(WrapTimeout), ReadOnly);
     v8->Set(String::New("version"), String::New(V8::GetVersion()),    ReadOnly);
 
@@ -2184,5 +2295,10 @@
     global->Set(String::New("Event"), evt, ReadOnly);
 
+    Handle<FunctionTemplate> desc = FunctionTemplate::New();
+    desc->SetClassName(String::New("Description"));
+    global->Set(String::New("Description"), desc, ReadOnly);
+
     fTemplateEvent = evt;
+    fTemplateDescription = desc;
 
 #ifdef HAVE_NOVA
Index: /trunk/FACT++/src/InterpreterV8.h
===================================================================
--- /trunk/FACT++/src/InterpreterV8.h	(revision 15072)
+++ /trunk/FACT++/src/InterpreterV8.h	(revision 15073)
@@ -50,4 +50,5 @@
     static v8::Handle<v8::FunctionTemplate> fTemplateSky;
     static v8::Handle<v8::FunctionTemplate> fTemplateEvent;
+    static v8::Handle<v8::FunctionTemplate> fTemplateDescription;
 
 #ifdef HAVE_SQL
@@ -67,4 +68,5 @@
     v8::Handle<v8::Value> FuncSend(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncSleep(const v8::Arguments& args);
+    v8::Handle<v8::Value> FuncTimeout(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncThread(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncKill(const v8::Arguments& args);
@@ -124,4 +126,5 @@
     static v8::Handle<v8::Value> WrapSend(const v8::Arguments &args)     { if (This) return This->FuncSend(args);     else return v8::Undefined(); }
     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> WrapThread(const v8::Arguments &args)   { if (This) return This->FuncThread(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(); }
