changeset 216:3a15cfb00a39

Bug 3765: pthread mutex lock/unlock enhancement Reviewed-by: ykubota https://github.com/HeapStats/heapstats/pull/150
author Yasumasa Suenaga <yasuenag@gmail.com>
date Sun, 10 Nov 2019 00:26:38 +0900
parents 866500a172fa
children 911de1085b7c
files ChangeLog agent/src/heapstats-engines/agentThread.cpp agent/src/heapstats-engines/deadlockFinder.cpp agent/src/heapstats-engines/fsUtil.cpp agent/src/heapstats-engines/gcWatcher.cpp agent/src/heapstats-engines/logMain.cpp agent/src/heapstats-engines/logManager.cpp agent/src/heapstats-engines/snapShotContainer.cpp agent/src/heapstats-engines/snapShotMain.cpp agent/src/heapstats-engines/snapShotProcessor.cpp agent/src/heapstats-engines/timer.cpp agent/src/heapstats-engines/trapSender.hpp agent/src/heapstats-engines/util.hpp
diffstat 13 files changed, 170 insertions(+), 162 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Apr 08 22:03:49 2018 +0900
+++ b/ChangeLog	Sun Nov 10 00:26:38 2019 +0900
@@ -1,3 +1,7 @@
+2019-11-10  Yasumasa Suenaga <yasuenag@gmail.com>
+
+	* Bug 3765: pthread mutex lock/unlock enhancement
+
 2018-04-08  Yasumasa Suenaga <yasuenag@gmail.com>
 
 	* Bug 3570: Build warning on Arm box
--- a/agent/src/heapstats-engines/agentThread.cpp	Sun Apr 08 22:03:49 2018 +0900
+++ b/agent/src/heapstats-engines/agentThread.cpp	Sun Nov 10 00:26:38 2019 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file agentThread.cpp
  * \brief This file is used to work on Jthread.
- * Copyright (C) 2011-2015 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2019 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -107,12 +107,11 @@
  * \brief Notify timing to this thread from other thread.
  */
 void TAgentThread::notify(void) {
+  TMutexLocker locker(&this->mutex);
+
   /* Send notification and count notify. */
-  ENTER_PTHREAD_SECTION(&this->mutex) {
-    this->_numRequests++;
-    pthread_cond_signal(&this->mutexCond);
-  }
-  EXIT_PTHREAD_SECTION(&this->mutex)
+  this->_numRequests++;
+  pthread_cond_signal(&this->mutexCond);
 }
 
 /*!
@@ -126,11 +125,12 @@
   }
 
   /* Send notification and count notify. */
-  ENTER_PTHREAD_SECTION(&this->mutex) {
+  {
+    TMutexLocker locker(&this->mutex);
+
     this->_terminateRequest = true;
     pthread_cond_signal(&this->mutexCond);
   }
-  EXIT_PTHREAD_SECTION(&this->mutex)
 
   /* SpinLock for AgentThread termination. */
   while (this->_isRunning) {
--- a/agent/src/heapstats-engines/deadlockFinder.cpp	Sun Apr 08 22:03:49 2018 +0900
+++ b/agent/src/heapstats-engines/deadlockFinder.cpp	Sun Nov 10 00:26:38 2019 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file deadlockFinder.cpp
  * \brief This file is used by find deadlock.
- * Copyright (C) 2011-2016 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2019 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -589,11 +589,17 @@
   controller->_isRunning = true;
 
   /* Loop for agent run. */
-  while (!controller->_terminateRequest) {
+  while (true) {
     /* Variable for notification flag. */
     bool needProcess = false;
 
-    ENTER_PTHREAD_SECTION(&controller->mutex) {
+    {
+      TMutexLocker locker(&controller->mutex);
+
+      if (controller->_terminateRequest) {
+        break;
+      }
+
       /* If no exists request. */
       if (likely(controller->_numRequests == 0)) {
         /* Wait for notification or termination. */
@@ -610,7 +616,6 @@
         controller->timeList.pop();
       }
     }
-    EXIT_PTHREAD_SECTION(&controller->mutex)
 
     /* If get notification. */
     if (likely(needProcess)) {
@@ -641,7 +646,9 @@
 void TDeadlockFinder::notify(jlong aTime) {
   bool raiseException = true;
   /* Send notification and count notify. */
-  ENTER_PTHREAD_SECTION(&this->mutex) {
+  {
+    TMutexLocker locker(&this->mutex);
+
     try {
       /* Store and count data. */
       timeList.push(aTime);
@@ -659,7 +666,6 @@
        */
     }
   }
-  EXIT_PTHREAD_SECTION(&this->mutex)
 
   if (unlikely(raiseException)) {
     throw "Failed to TDeadlockFinder notify";
--- a/agent/src/heapstats-engines/fsUtil.cpp	Sun Apr 08 22:03:49 2018 +0900
+++ b/agent/src/heapstats-engines/fsUtil.cpp	Sun Nov 10 00:26:38 2019 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file fsUtil.cpp
  * \brief This file is utilities to access file system.
- * Copyright (C) 2011-2015 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2019 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -242,8 +242,8 @@
   }
 
   int raisedErrNum = -1;
-  /* Get mutex. */
-  ENTER_PTHREAD_SECTION(&directoryMutex) {
+  {
+    TMutexLocker locker(&directoryMutex);
 
     /* Create unique directory path. */
     uniqName = createUniquePath((char *)wishesName, true);
@@ -258,8 +258,6 @@
       }
     }
   }
-  /* Release mutex. */
-  EXIT_PTHREAD_SECTION(&directoryMutex)
 
   /* If failed to create temporary directory. */
   if (unlikely(raisedErrNum != 0)) {
@@ -330,8 +328,8 @@
   /* Cleanup. */
   closedir(dir);
 
-  /* Get mutex. */
-  ENTER_PTHREAD_SECTION(&directoryMutex) {
+  {
+    TMutexLocker locker(&directoryMutex);
 
     /* Remove directory. */
     if (unlikely(rmdir(basePath) != 0)) {
@@ -340,8 +338,6 @@
     }
 
   }
-  /* Release mutex. */
-  EXIT_PTHREAD_SECTION(&directoryMutex)
 }
 
 /*!
--- a/agent/src/heapstats-engines/gcWatcher.cpp	Sun Apr 08 22:03:49 2018 +0900
+++ b/agent/src/heapstats-engines/gcWatcher.cpp	Sun Nov 10 00:26:38 2019 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file gcWatcher.cpp
  * \brief This file is used to take snapshot when finish garbage collection.
- * Copyright (C) 2011-2015 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2019 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -62,11 +62,17 @@
   controller->_isRunning = true;
 
   /* Loop for agent run. */
-  while (!controller->_terminateRequest) {
+  while (true) {
     /* Variable for notification flag. */
     bool needProcess = false;
 
-    ENTER_PTHREAD_SECTION(&controller->mutex) {
+    {
+      TMutexLocker locker(&controller->mutex);
+
+      if (controller->_terminateRequest) {
+        break;
+      }
+
       /* If no exists request. */
       if (likely(controller->_numRequests == 0)) {
         /* Wait for notification or termination. */
@@ -79,7 +85,6 @@
         needProcess = true;
       }
     }
-    EXIT_PTHREAD_SECTION(&controller->mutex)
 
     /* If waiting finished by notification. */
     if (needProcess) {
--- a/agent/src/heapstats-engines/logMain.cpp	Sun Apr 08 22:03:49 2018 +0900
+++ b/agent/src/heapstats-engines/logMain.cpp	Sun Nov 10 00:26:38 2019 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file logmain.cpp
  * \brief This file is used common logging process.
- * Copyright (C) 2011-2017 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2019 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -237,8 +237,8 @@
   }
 
   bool isCollectLog = true;
-  /* Lock to use in multi-thread. */
-  ENTER_PTHREAD_SECTION(&errMutex) {
+  {
+    TMutexLocker locker(&errMutex);
 
     /* If collected already and collect first only. */
     if (conf->FirstCollect()->get() && conf->isFirstCollected()) {
@@ -249,8 +249,6 @@
     conf->setFirstCollected(true);
 
   }
-  /* Unlock to use in multi-thread. */
-  EXIT_PTHREAD_SECTION(&errMutex)
 
   if (isCollectLog) {
     /* Setting collect log cause. */
--- a/agent/src/heapstats-engines/logManager.cpp	Sun Apr 08 22:03:49 2018 +0900
+++ b/agent/src/heapstats-engines/logManager.cpp	Sun Nov 10 00:26:38 2019 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file logManager.cpp
  * \brief This file is used collect log information.
- * Copyright (C) 2011-2016 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2019 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -255,8 +255,8 @@
            /* Params : Archive file name. */
            archivePath);
 
-  /* Get mutex. */
-  ENTER_PTHREAD_SECTION(&logMutex) {
+  {
+    TMutexLocker locker(&logMutex);
 
     /* Open log file. */
     int fd = open(conf->HeapLogFile()->get(), O_CREAT | O_WRONLY | O_APPEND,
@@ -282,8 +282,7 @@
       }
     }
   }
-  /* Release mutex. */
-  EXIT_PTHREAD_SECTION(&logMutex)
+
   return result;
 }
 
@@ -379,8 +378,8 @@
      */
     result = -1;
 
-    /* Get mutex. */
-    ENTER_PTHREAD_SECTION(&archiveMutex) {
+    {
+      TMutexLocker locker(&archiveMutex);
 
       /* Create archive file name. */
       uniqArcName = createArchiveName(nowTime);
@@ -400,8 +399,6 @@
         }
       }
     }
-    /* Release mutex. */
-    EXIT_PTHREAD_SECTION(&archiveMutex)
 
     /* If failure create archive file yet. */
     if (unlikely(result != 0)) {
--- a/agent/src/heapstats-engines/snapShotContainer.cpp	Sun Apr 08 22:03:49 2018 +0900
+++ b/agent/src/heapstats-engines/snapShotContainer.cpp	Sun Nov 10 00:26:38 2019 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file snapshotContainer.cpp
  * \brief This file is used to add up using size every class.
- * Copyright (C) 2011-2017 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2019 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -89,27 +89,26 @@
  *          Please call "releaseInstance" method.
  */
 TSnapShotContainer *TSnapShotContainer::getInstance(void) {
+  TMutexLocker locker(&instanceLocker);
+
   TSnapShotContainer *result = NULL;
 
-  ENTER_PTHREAD_SECTION(&instanceLocker) {
-    if (!stockQueue->empty()) {
-      /* Reuse snapshot container instance. */
-      result = stockQueue->front();
-      stockQueue->pop();
-    }
+  if (!stockQueue->empty()) {
+    /* Reuse snapshot container instance. */
+    result = stockQueue->front();
+    stockQueue->pop();
+  }
 
-    /* If need create new instance. */
-    if (result == NULL) {
-      /* Create new snapshot container instance. */
-      try {
-        result = new TSnapShotContainer();
-        activeSnapShots.insert(result);
-      } catch (...) {
-        result = NULL;
-      }
+  /* If need create new instance. */
+  if (result == NULL) {
+    /* Create new snapshot container instance. */
+    try {
+      result = new TSnapShotContainer();
+      activeSnapShots.insert(result);
+    } catch (...) {
+      result = NULL;
     }
   }
-  EXIT_PTHREAD_SECTION(&instanceLocker)
 
   return result;
 }
@@ -126,10 +125,11 @@
   }
 
   bool existStockSpace = false;
-  ENTER_PTHREAD_SECTION(&instanceLocker) {
+  {
+    TMutexLocker locker(&instanceLocker);
+
     existStockSpace = (stockQueue->size() < MAX_STOCK_COUNT);
   }
-  EXIT_PTHREAD_SECTION(&instanceLocker)
 
   if (likely(existStockSpace)) {
     /*
@@ -143,7 +143,9 @@
     /* Clear data. */
     instance->clear(false);
 
-    ENTER_PTHREAD_SECTION(&instanceLocker) {
+    {
+      TMutexLocker locker(&instanceLocker);
+
       try {
         /* Store instance. */
         stockQueue->push(instance);
@@ -153,18 +155,17 @@
         /* Maybe faield to allocate memory. So we release instance. */
       }
     }
-    EXIT_PTHREAD_SECTION(&instanceLocker)
   }
 
-  ENTER_PTHREAD_SECTION(&instanceLocker)
   {
+    TMutexLocker locker(&instanceLocker);
+
     if (unlikely(!existStockSpace)) {
       /* Deallocate instance. */
       activeSnapShots.erase(instance);
       delete instance;
     }
   }
-  EXIT_PTHREAD_SECTION(&instanceLocker)
 }
 
 /*!
@@ -572,13 +573,11 @@
  */
 void TSnapShotContainer::removeObjectDataFromAllSnapShots(
                                                  TClassInfoSet &unloadedList) {
-  ENTER_PTHREAD_SECTION(&instanceLocker)
-  {
-    for (TActiveSnapShots::iterator itr = activeSnapShots.begin();
-         itr != activeSnapShots.end(); itr++) {
-      (*itr)->removeObjectData(unloadedList);
-    }
+  TMutexLocker locker(&instanceLocker);
+
+  for (TActiveSnapShots::iterator itr = activeSnapShots.begin();
+       itr != activeSnapShots.end(); itr++) {
+    (*itr)->removeObjectData(unloadedList);
   }
-  EXIT_PTHREAD_SECTION(&instanceLocker)
 }
 
--- a/agent/src/heapstats-engines/snapShotMain.cpp	Sun Apr 08 22:03:49 2018 +0900
+++ b/agent/src/heapstats-engines/snapShotMain.cpp	Sun Nov 10 00:26:38 2019 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file snapShotMain.cpp
  * \brief This file is used to take snapshot.
- * Copyright (C) 2011-2017 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2019 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -183,7 +183,9 @@
 inline bool addSnapShotQueue(TSnapShotContainer *snapshot) {
   bool isSucceed = false;
   /* Push output waiting queue. */
-  ENTER_PTHREAD_SECTION(&queueMutex) {
+  {
+    TMutexLocker locker(&queueMutex);
+
     try {
       snapStockQueue.push(snapshot);
 
@@ -196,7 +198,6 @@
        */
     }
   }
-  EXIT_PTHREAD_SECTION(&queueMutex)
 
   return isSucceed;
 }
@@ -210,13 +211,14 @@
   TSnapShotContainer *snapshot = NULL;
 
   /* Get snapshot data from waiting queue. */
-  ENTER_PTHREAD_SECTION(&queueMutex) {
+  {
+    TMutexLocker locker(&queueMutex);
+
     if (likely(!snapStockQueue.empty())) {
       snapshot = snapStockQueue.front();
       snapStockQueue.pop();
     }
   }
-  EXIT_PTHREAD_SECTION(&queueMutex)
 
   return snapshot;
 }
@@ -589,11 +591,9 @@
   /* Avoid the plural simultaneous take snapshot by dump-request.        */
   /* E.g. keeping pushed dump key.                                       */
   /* Because classContainer register a redundancy class in TakeSnapShot. */
-  ENTER_PTHREAD_SECTION(&dumpMutex) {
-    /* Make snapshot. */
-    TakeSnapShot(jvmti, NULL, DataDumpRequest);
-  }
-  EXIT_PTHREAD_SECTION(&dumpMutex)
+  TMutexLocker locker(&dumpMutex);
+
+  TakeSnapShot(jvmti, NULL, DataDumpRequest);
 }
 
 /*!
@@ -633,22 +633,21 @@
 
     if (likely(snapshot != NULL)) {
       /* Lock to avoid doubling call JVMTI. */
-      ENTER_PTHREAD_SECTION(&jvmtiMutex) {
-        snapshotByJvmti = snapshot;
+      TMutexLocker locker(&jvmtiMutex);
+
+      snapshotByJvmti = snapshot;
 
-        /* Enable JVMTI hooking. */
-        if (likely(setJvmtiHookState(true))) {
-          /* Count object size on heap. */
-          error = jvmti->IterateOverHeap(JVMTI_HEAP_OBJECT_EITHER,
-                                         &HeapObjectCallBack, NULL);
+      /* Enable JVMTI hooking. */
+      if (likely(setJvmtiHookState(true))) {
+        /* Count object size on heap. */
+        error = jvmti->IterateOverHeap(JVMTI_HEAP_OBJECT_EITHER,
+                                       &HeapObjectCallBack, NULL);
 
-          /* Disable JVMTI hooking. */
-          setJvmtiHookState(false);
-        }
+        /* Disable JVMTI hooking. */
+        setJvmtiHookState(false);
+      }
 
-        snapshotByJvmti = NULL;
-      }
-      EXIT_PTHREAD_SECTION(&jvmtiMutex)
+      snapshotByJvmti = NULL;
     }
 
     if (likely(error == JVMTI_ERROR_NONE)) {
--- a/agent/src/heapstats-engines/snapShotProcessor.cpp	Sun Apr 08 22:03:49 2018 +0900
+++ b/agent/src/heapstats-engines/snapShotProcessor.cpp	Sun Nov 10 00:26:38 2019 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file snapShotProcessor.cpp
  * \brief This file is used to output ranking and call snapshot function.
- * Copyright (C) 2011-2017 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2019 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -69,12 +69,18 @@
 
   bool existRemainder = false;
   /* Loop for agent run or remaining work exist. */
-  while (!controller->_terminateRequest || existRemainder) {
+  while (true) {
     TSnapShotContainer *snapshot = NULL;
     /* Is notify flag. */
     bool needProcess = false;
 
-    ENTER_PTHREAD_SECTION(&controller->mutex) {
+    {
+      TMutexLocker locker(&controller->mutex);
+
+      if (controller->_terminateRequest && !existRemainder) {
+        break;
+      }
+
       if (likely(controller->_numRequests == 0)) {
         /* Wait for notification or termination. */
         pthread_cond_wait(&controller->mutexCond, &controller->mutex);
@@ -93,7 +99,6 @@
       /* Check remaining work. */
       existRemainder = (controller->_numRequests > 0);
     }
-    EXIT_PTHREAD_SECTION(&controller->mutex)
 
     /* If waiting is finished by notification. */
     if (needProcess && (snapshot != NULL)) {
@@ -160,7 +165,9 @@
 
   bool raiseException = true;
   /* Send notification and count notify. */
-  ENTER_PTHREAD_SECTION(&this->mutex) {
+  {
+    TMutexLocker locker(&this->mutex);
+
     try {
       /* Store and count data. */
       snapQueue.push(snapshot);
@@ -178,7 +185,6 @@
        */
     }
   }
-  EXIT_PTHREAD_SECTION(&this->mutex)
 
   if (unlikely(raiseException)) {
     throw "Failed to TSnapShotProcessor notify";
--- a/agent/src/heapstats-engines/timer.cpp	Sun Apr 08 22:03:49 2018 +0900
+++ b/agent/src/heapstats-engines/timer.cpp	Sun Nov 10 00:26:38 2019 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file timer.cpp
  * \brief This file is used to take interval snapshot.
- * Copyright (C) 2011-2015 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2019 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -72,11 +72,17 @@
   controller->_isRunning = true;
 
   /* Loop for agent run. */
-  while (!controller->_terminateRequest) {
+  while (true) {
     /* Reset timer interrupt flag. */
     controller->_isInterrupted = false;
 
-    ENTER_PTHREAD_SECTION(&controller->mutex) {
+    {
+      TMutexLocker locker(&controller->mutex);
+
+      if (controller->_terminateRequest) {
+        break;
+      }
+
       /* Create limit datetime. */
       struct timespec limitTs = {0};
       struct timeval nowTv = {0};
@@ -89,7 +95,6 @@
       pthread_cond_timedwait(&controller->mutexCond, &controller->mutex,
                              &limitTs);
     }
-    EXIT_PTHREAD_SECTION(&controller->mutex)
 
     /* If waiting finished by timeout. */
     if (!controller->_isInterrupted) {
@@ -166,11 +171,10 @@
 
   } else {
     /* Set interrupt flag and notify. */
-    ENTER_PTHREAD_SECTION(&this->mutex) {
-      this->_isInterrupted = true;
-      pthread_cond_signal(&this->mutexCond);
-    }
-    EXIT_PTHREAD_SECTION(&this->mutex)
+    TMutexLocker locker(&this->mutex);
+
+    this->_isInterrupted = true;
+    pthread_cond_signal(&this->mutexCond);
   }
 }
 
--- a/agent/src/heapstats-engines/trapSender.hpp	Sun Apr 08 22:03:49 2018 +0900
+++ b/agent/src/heapstats-engines/trapSender.hpp	Sun Nov 10 00:26:38 2019 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file trapSender.hpp
  * \brief This file is used to send SNMP trap.
- * Copyright (C) 2011-2017 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2019 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -183,55 +183,47 @@
    * \param port      [in] Port used by SNMP trap.
    */
   TTrapSender(int snmp, char *pPeer, char *pCommName, int port) {
-    /* Lock to use in multi-thread. */
-    ENTER_PTHREAD_SECTION(&senderMutex) {
+    TMutexLocker locker(&senderMutex);
 
-      /* Disable NETSNMP logging. */
-      netsnmp_register_loghandler(NETSNMP_LOGHANDLER_NONE, LOG_EMERG);
+    /* Disable NETSNMP logging. */
+    netsnmp_register_loghandler(NETSNMP_LOGHANDLER_NONE, LOG_EMERG);
 
-      /* If snmp target is illegal. */
-      if (pPeer == NULL) {
-        logger->printWarnMsg("Illegal SNMP target.");
-        pPdu = NULL;
-      } else {
-        /* Initialize session. */
-        memset(&session, 0, sizeof(netsnmp_session));
-        snmp_sess_init(&session);
-        session.version = snmp;
-        session.peername = strdup(pPeer);
-        session.remote_port = port;
-        session.community = (u_char *)strdup(pCommName);
-        session.community_len = (pCommName != NULL) ? strlen(pCommName) : 0;
+    /* If snmp target is illegal. */
+    if (pPeer == NULL) {
+      logger->printWarnMsg("Illegal SNMP target.");
+      pPdu = NULL;
+    } else {
+      /* Initialize session. */
+      memset(&session, 0, sizeof(netsnmp_session));
+      snmp_sess_init(&session);
+      session.version = snmp;
+      session.peername = strdup(pPeer);
+      session.remote_port = port;
+      session.community = (u_char *)strdup(pCommName);
+      session.community_len = (pCommName != NULL) ? strlen(pCommName) : 0;
 
-        /* Make a PDU */
-        pPdu = snmp_pdu_create(SNMP_MSG_TRAP2);
-      }
+      /* Make a PDU */
+      pPdu = snmp_pdu_create(SNMP_MSG_TRAP2);
     }
-    /* Unlock to use in multi-thread. */
-    EXIT_PTHREAD_SECTION(&senderMutex)
   }
 
   /*!
    * \brief TrapSender destructor.
    */
   ~TTrapSender(void) {
-    /* Lock to use in multi-thread. */
-    ENTER_PTHREAD_SECTION(&senderMutex) {
+    TMutexLocker locker(&senderMutex);
 
-      /* Clear Allocated str. */
-      clearValues();
+    /* Clear Allocated str. */
+    clearValues();
 
-      /* Free SNMP pdu. */
-      if (pPdu != NULL) {
-        snmp_free_pdu(pPdu);
-      }
-      /* Close and free SNMP session. */
-      snmp_close(&session);
-      free(session.peername);
-      free(session.community);
+    /* Free SNMP pdu. */
+    if (pPdu != NULL) {
+      snmp_free_pdu(pPdu);
     }
-    /* Unlock to use in multi-thread. */
-    EXIT_PTHREAD_SECTION(&senderMutex)
+    /* Close and free SNMP session. */
+    snmp_close(&session);
+    free(session.peername);
+    free(session.community);
   }
 
   /*!
--- a/agent/src/heapstats-engines/util.hpp	Sun Apr 08 22:03:49 2018 +0900
+++ b/agent/src/heapstats-engines/util.hpp	Sun Nov 10 00:26:38 2019 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file util.hpp
  * \brief This file is utilities.
- * Copyright (C) 2011-2017 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2019 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -25,9 +25,11 @@
 #include <jvmti.h>
 #include <jni.h>
 
+#include <assert.h>
 #include <stddef.h>
 #include <errno.h>
 #include <string.h>
+#include <pthread.h>
 
 /* Branch prediction. */
 
@@ -41,23 +43,23 @@
  */
 #define unlikely(x) __builtin_expect(!!(x), 0)
 
-/* Critical section helper macro for pthread mutex. */
-
 /*!
- * \brief Enter critical pthread section macro.
+ * \brief C++ class for pthread mutex.
+ *        C'tor acquires mutex, and d'tor releases it.
  */
-#define ENTER_PTHREAD_SECTION(monitor)                \
-  if (unlikely(pthread_mutex_lock((monitor)) != 0)) { \
-    logger->printWarnMsg("Entering mutex failed!");   \
-  } else {
-/*!
- * \brief Exit critical pthread section macro.
- */
-#define EXIT_PTHREAD_SECTION(monitor)                   \
-  if (unlikely(pthread_mutex_unlock((monitor)) != 0)) { \
-    logger->printWarnMsg("Exiting mutex failed!");      \
-  }                                                     \
-  }
+class TMutexLocker {
+  private:
+    pthread_mutex_t *_mutex;
+
+  public:
+    TMutexLocker(pthread_mutex_t *mutex) : _mutex(mutex) {
+      assert(pthread_mutex_lock(_mutex) == 0);
+    }
+
+    ~TMutexLocker() {
+      assert(pthread_mutex_unlock(_mutex) == 0);
+    }
+};
 
 /*!
  * \brief Calculate align macro.