[AGENT++] New Releases of AGENT++, AgentX++ and Tool Suite

Claus Klein claus.klein at arcormail.de
Mon Feb 19 08:30:56 CET 2018


Hi Frank,

I have checked the new version with xcode on my macbook.

I’m Sorry to say, but there are still problems:

First of all, it does not compile on mac OSX!
Darwin Kernel Version 15.6.0: Tue Jan  9 20:12:05 PST 2018; root:xnu-3248.73.5~1/RELEASE_X86_64
The pthread_mutex_timedlock() is still not availble on OSX.

2.) the Synchronized::trylock() return the wrong result
     The pthread_mutex_trylock() return:

     [EBUSY]            if Mutex is already locked!

3.) the QueuedThreadPool does execute the tasks in random order
	NOTE: This should not defined AGENTPP_QUEUED_THREAD_POOL_USE_ASSIGN; see below

4.) there are still race conditions at code
void TaskManager::run()
{
    lock();
    while (go) {
        if (task) {
            task->run();
            delete task;
            task = 0;
            unlock();	<<<<<<<<<<<<<<<<<<<
            threadPool->idle_notification();
            lock();		<<<<<<<<<<<<<<<<<<<
        } else {
            wait();
        }
    }
    if (task) {
        delete task;
        task = 0;
    }
    unlock();
}

5.) The code is still not exception save at all!


With regards

Claus Klein


P.S. this patch fix some of the problems, but not all; please check:


diff --git a/include/agent_pp/threads.h b/include/agent_pp/threads.h
index e722a89..9e088b0 100644
--- a/include/agent_pp/threads.h
+++ b/include/agent_pp/threads.h
@@ -19,8 +19,8 @@
   _##########################################################################*/
 
 
-#ifndef multi_h_
-#define multi_h_
+#ifndef agent_pp_threads_h_
+#define agent_pp_threads_h_
 
 #include <agent_pp/agent++.h>
 
@@ -552,7 +552,7 @@ public:
      *    TRUE if non of the threads in the pool is currently
      *    executing any task.
      */
-    bool is_idle();
+    virtual bool is_idle();
 
     /**
      * Check whether the ThreadPool is busy (i.e., all threads are
@@ -562,7 +562,7 @@ public:
      *    TRUE if non of the threads in the pool is currently
      *    idle (not executing any task).
      */
-    bool is_busy();
+    virtual bool is_busy();
 
     /**
      * Get the size of the thread pool.
@@ -655,13 +655,31 @@ public:
      */
     void execute(Runnable*);
 
+    /**
+     * Check whether the ThreadPool is idle or not.
+     *
+     * @return
+     *    TRUE if non of the threads in the pool is currently
+     *    executing any task and the queue is empty.
+     */
+    virtual bool is_idle();
+
+    /**
+     * Check whether the ThreadPool is busy (i.e., all threads are
+     * running a task) or not.
+     *
+     * @return
+     *    TRUE if the queue is not empty or the pool is_busy()
+     */
+    virtual bool is_busy();
+
     /**
      * Gets the current number of queued tasks.
      *
      * @return
      *    the number of tasks that are currently queued.
      */
-    unsigned int queue_length() { return queue.size(); }
+    unsigned int queue_length(); // FIXME: not thread save! { return queue.size(); }
 
 
     /**
diff --git a/src/threads.cpp b/src/threads.cpp
index 3942a7e..26b02a6 100644
--- a/src/threads.cpp
+++ b/src/threads.cpp
@@ -1148,7 +1148,21 @@ void QueuedThreadPool::assign(Runnable* t)
 void QueuedThreadPool::execute(Runnable* t)
 {
     Thread::lock();
-    assign(t);
+
+#ifdef AGENTPP_QUEUED_THREAD_POOL_USE_ASSIGN
+    if (queue.empty()) {
+        assign(t);
+    } else
+#endif
+
+    {
+        LOG_BEGIN(loggerModuleName, DEBUG_LOG | 1);
+        LOG("queue.push");
+        LOG_END;
+        queue.add(t);
+        Thread::notify();
+    }
+
     Thread::unlock();
 }
 
@@ -1169,14 +1183,47 @@ void QueuedThreadPool::run()
     Thread::unlock();
 }
 
+unsigned int QueuedThreadPool::queue_length()
+{
+    Thread::lock();
+    unsigned len = queue.size();
+    Thread::unlock();
+
+    return len;
+}
+
 void QueuedThreadPool::idle_notification()
 {
+    LOG_BEGIN(loggerModuleName, DEBUG_LOG | 1);
+    LOG("idle_notification");
+    LOG_END;
+
     Thread::lock();
     Thread::notify();
     Thread::unlock();
+
     ThreadPool::idle_notification();
 }
 
+bool QueuedThreadPool::is_idle()
+{
+    Thread::lock();
+    bool result = is_alive() && queue.empty() && ThreadPool::is_idle();
+    Thread::unlock();
+
+    return result;
+}
+
+bool QueuedThreadPool::is_busy()
+{
+    Thread::lock();
+    bool result = !queue.empty() || ThreadPool::is_busy();
+    Thread::unlock();
+
+    return result;
+}
+
+/*--------------------- class LockRequest --------------------------*/
 
 void MibTask::run() { (task->called_class->*task->method)(task->req); }
 


> Am 23.01.2018 um 23:28 schrieb Frank Fock <fock at agentpp.com>:
> 
> AGENT++ 4.1.0: (SNMP++ 3.3.10 or later)
> 
> * Changed: CAUTION: Thread policy changed from RECURSIVE to ERRORCHECK in
>  this release. You should carefully test your instrumentation code locking
>  (start_synch()) before using this release with your instrumentation 
>  in production!
> * Improved: Incoming Request objects are now always locked using a LockQueue
>  for SNMP requests, in order to allow several threads to work with those 
>  request objects during different phase of the request (i.e. SET request 
>  phase or GETBULK processing in conjunction with proxies or subagents).
> * Fixed [APP-48]: ThreadPool may not execute a task if one of its threads 
>  is not properly started.



More information about the AGENTPP mailing list