diff --git a/Common/GmshMessage.cpp b/Common/GmshMessage.cpp
index 02f09aed2b41f0c03f349ee1e7ae5a9dd7aa1b3a..bcd9f083fed433347c793d4c4dfff26a42b0c66a 100644
--- a/Common/GmshMessage.cpp
+++ b/Common/GmshMessage.cpp
@@ -55,7 +55,7 @@ int Msg::_commRank = 0;
 int Msg::_commSize = 1;
 int Msg::_verbosity = 5;
 int Msg::_progressMeterStep = 10;
-int Msg::_progressMeterCurrent = -1;
+std::atomic<int> Msg::_progressMeterCurrent(-1);
 int Msg::_progressMeterTotal = 0;
 std::map<std::string, double> Msg::_timers;
 bool Msg::_infoCpu = false;
@@ -595,8 +595,10 @@ void Msg::Info(const char *fmt, ...)
 
   if(CTX::instance()->terminal){
     if(_progressMeterCurrent >= 0 && _progressMeterTotal > 1 &&
-       _commSize == 1)
-      fprintf(stdout, "Info    : [%3d%%] %s\n", _progressMeterCurrent, str);
+       _commSize == 1) {
+      int p =  _progressMeterCurrent;
+      fprintf(stdout, "Info    : [%3d%%] %s\n", p, str);
+    }
     else if(_commSize > 1)
       fprintf(stdout, "Info    : [rank %3d] %s\n", GetCommRank(), str);
     else
@@ -773,24 +775,18 @@ void Msg::ProgressMeter(int n, bool log, const char *fmt, ...)
     while(p < percent) p += _progressMeterStep;
     if(p >= 100) p = 100;
 
-#if defined(_OPENMP)
-#pragma omp critical
-#endif
-    {
-      _progressMeterCurrent = p;
-    }
+    _progressMeterCurrent = p;
 
     // TODO With C++11 use std::string (contiguous layout) and avoid all these C
     // problems
     // str2 needs to have at least 5018 bytes or buffer overflow will occur
-    char str[5000], str2[5018];
+    char str[5000], str2[5100];
     va_list args;
     va_start(args, fmt);
     vsnprintf(str, sizeof(str), fmt, args);
     va_end(args);
     int l = strlen(str); if(str[l - 1] == '\n') str[l - 1] = '\0';
-
-    sprintf(str2, "Info    : [%3d%%] %s", _progressMeterCurrent, str);
+    sprintf(str2, "Info    : [%3d%%] %s", p, str);
 
     if(_client) _client->Progress(str2);
 
diff --git a/Common/GmshMessage.h b/Common/GmshMessage.h
index 939738542e7c1ac539d048b810930341c3a87541..3ca21a84f9e92d57201afbcace27d22eae2fe05c 100644
--- a/Common/GmshMessage.h
+++ b/Common/GmshMessage.h
@@ -9,6 +9,7 @@
 #include <map>
 #include <vector>
 #include <string>
+#include <atomic>
 #include <stdarg.h>
 
 #include "GmshConfig.h"
@@ -35,7 +36,8 @@ private:
   // 3: +direct, 4: +info, 5 (=normal): +statusbar, 99: debug)
   static int _verbosity;
   // step (in %) of the progress meter and current progress (in %)
-  static int _progressMeterStep, _progressMeterCurrent;
+  static int _progressMeterStep;
+  static std::atomic<int> _progressMeterCurrent;
   // total number of items considered in the current progress meter calculation
   static int _progressMeterTotal;
   // timers
diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp
index 365f3adc0008f311afb8260860fbda33090c591a..8915b2a333992b70e7dc5cd19be11580ab76fc41 100644
--- a/Geo/GModel.cpp
+++ b/Geo/GModel.cpp
@@ -210,18 +210,26 @@ void GModel::destroy(bool keepName)
 
 void GModel::destroyMeshCaches()
 {
-  _vertexVectorCache.clear();
-  std::vector<MVertex *>().swap(_vertexVectorCache);
-  _vertexMapCache.clear();
-  std::map<int, MVertex *>().swap(_vertexMapCache);
-  _elementVectorCache.clear();
-  std::vector<MElement *>().swap(_elementVectorCache);
-  _elementMapCache.clear();
-  std::map<int, MElement *>().swap(_elementMapCache);
-  _elementIndexCache.clear();
-  std::map<int, int>().swap(_elementIndexCache);
-  delete _elementOctree;
-  _elementOctree = nullptr;
+  // this is called in GEntity::deleteMesh()
+#if defined(_OPENMP)
+#pragma omp critical
+#endif
+  {
+    _vertexVectorCache.clear();
+    std::vector<MVertex *>().swap(_vertexVectorCache);
+    _vertexMapCache.clear();
+    std::map<int, MVertex *>().swap(_vertexMapCache);
+    _elementVectorCache.clear();
+    std::vector<MElement *>().swap(_elementVectorCache);
+    _elementMapCache.clear();
+    std::map<int, MElement *>().swap(_elementMapCache);
+    _elementIndexCache.clear();
+    std::map<int, int>().swap(_elementIndexCache);
+    if(_elementOctree) {
+      delete _elementOctree;
+      _elementOctree = nullptr;
+    }
+  }
 }
 
 void GModel::deleteMesh()
@@ -1946,6 +1954,14 @@ void GModel::scaleMesh(double factor)
     }
 }
 
+void GModel::setCurrentMeshEntity(GEntity *e)
+{
+#if defined(_OPENMP)
+#pragma omp critical
+#endif
+  _currentMeshEntity = e;
+}
+
 int GModel::partitionMesh(int numPart)
 {
 #if defined(HAVE_MESH) && (defined(HAVE_METIS))
diff --git a/Geo/GModel.h b/Geo/GModel.h
index 7367c0441a369b69617d97e7dfbcaca0129acbfd..cdd281ca39777fc3f5f78f374231ea835c56b805 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -561,7 +561,7 @@ public:
   void scaleMesh(double factor);
 
   // set/get entity that is currently being meshed (for error reporting)
-  void setCurrentMeshEntity(GEntity *e) { _currentMeshEntity = e; }
+  void setCurrentMeshEntity(GEntity *e);
   GEntity *getCurrentMeshEntity() { return _currentMeshEntity; }
 
   // set/get entities/vertices linked meshing errors
diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp
index 79f2924447c558524db7a215c571c15c613751b8..38ea85701d3d95db8b96f0f6287fa69e3e9fcb9d 100644
--- a/Mesh/Generator.cpp
+++ b/Mesh/Generator.cpp
@@ -379,17 +379,16 @@ static void Mesh1D(GModel *m)
 #pragma omp parallel for schedule(dynamic)
 #endif
     for(size_t K = 0; K < sss; K++) {
+      int localPending = 0;
       GEdge *ed = temp[K];
       if(ed->meshStatistics.status == GEdge::PENDING) {
         ed->mesh(true);
 #if defined(_OPENMP)
 #pragma omp critical
 #endif
-        {
-          nPending++;
-        }
+	localPending = ++nPending;
       }
-      if(!nIter) Msg::ProgressMeter(nPending, false, "Meshing 1D...");
+      if(!nIter) Msg::ProgressMeter(localPending, false, "Meshing 1D...");
     }
 
     if(!nPending) break;
@@ -530,17 +529,16 @@ static void Mesh2D(GModel *m)
 #pragma omp parallel for schedule(dynamic)
 #endif
       for(size_t K = 0; K < temp.size(); K++) {
+	int localPending = 0;
         if(temp[K]->meshStatistics.status == GFace::PENDING) {
           backgroundMesh::current()->unset();
           temp[K]->mesh(true);
 #if defined(_OPENMP)
 #pragma omp critical
 #endif
-          {
-            nPending++;
-          }
+	  localPending = ++nPending;
         }
-        if(!nIter) Msg::ProgressMeter(nPending, false, "Meshing 2D...");
+        if(!nIter) Msg::ProgressMeter(localPending, false, "Meshing 2D...");
       }
       if(!nPending) break;
       // iter == 2 is for meshing re-parametrized surfaces; after that, we