diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 9b12cc0262c5d6082f1605f83eb9a991e77d246a..2e32a7b7c44c3093cd1b321b8ac7e1e290a8e37a 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,3 +1,5 @@
+4.2.0: changed logger API.
+
 4.1.5 (February 14, 2019): improved OpenMP parallelization, STL remeshing, mesh
 partitioning and high-order mesh optimization; added classifySurfaces in API;
 bug fixes.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2757b45459fe1e373e2f99d203ab7c584723c383..b51131fae09b115b84c3afeea8baa490ab07b49d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -96,8 +96,8 @@ opt(WRAP_PYTHON "Enable generation of Python wrappers for private API" OFF)
 opt(ZIPPER "Enable Zip file compression/decompression" OFF)
 
 set(GMSH_MAJOR_VERSION 4)
-set(GMSH_MINOR_VERSION 1)
-set(GMSH_PATCH_VERSION 5)
+set(GMSH_MINOR_VERSION 2)
+set(GMSH_PATCH_VERSION 0)
 set(GMSH_EXTRA_VERSION "")
 set(GMSH_EXTRA_VERSION_TEXI "${GMSH_EXTRA_VERSION}")
 
@@ -1150,6 +1150,9 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/hxt AND
     file(GLOB_RECURSE HXT_SRC contrib/hxt/*.c)
     set_compile_flags(HXT_SRC "/TP")
   endif()
+  if(HAVE_PETSC)
+    add_definitions(-DHXT_HAVE_PETSC)
+  endif()
 endif()
 
 if(ENABLE_OCC)
diff --git a/Common/gmsh.cpp b/Common/gmsh.cpp
index 873fa764a5132b386e4299a6e3b8ad38c747ffd9..16cea74b086d20a4fcbe06f4f6cc62879a067571 100644
--- a/Common/gmsh.cpp
+++ b/Common/gmsh.cpp
@@ -4816,17 +4816,18 @@ GMSH_API void gmsh::logger::write(const std::string &message,
 
 class apiMsg : public GmshMessage {
 private:
-  std::vector<std::string> &_log;
+  std::vector<std::string> _log;
 
 public:
-  apiMsg(std::vector<std::string> &log) : _log(log) {}
+  apiMsg(){}
   virtual void operator()(std::string level, std::string message)
   {
     _log.push_back(level + ": " + message);
   }
+  void get(std::vector<std::string> &log) const { log = _log; }
 };
 
-GMSH_API void gmsh::logger::start(std::vector<std::string> &log)
+GMSH_API void gmsh::logger::start()
 {
   if(!_isInitialized()) {
     throw -1;
@@ -4836,11 +4837,25 @@ GMSH_API void gmsh::logger::start(std::vector<std::string> &log)
     Msg::Warning("Logger already started - ignoring");
   }
   else {
-    msg = new apiMsg(log);
+    msg = new apiMsg();
     Msg::SetCallback(msg);
   }
 }
 
+GMSH_API void gmsh::logger::get(std::vector<std::string> &log)
+{
+  if(!_isInitialized()) {
+    throw -1;
+  }
+  apiMsg *msg = dynamic_cast<apiMsg*>(Msg::GetCallback());
+  if(msg) {
+    msg->get(log);
+  }
+  else {
+    log.clear();
+  }
+}
+
 GMSH_API void gmsh::logger::stop()
 {
   if(!_isInitialized()) {
diff --git a/Solver/linearSystemPETSc.hpp b/Solver/linearSystemPETSc.hpp
index 52f50b63777b306d0b958793daba13cb773dcfcb..b3cb7ceffb9956497a5b1d57ed038849c514817b 100644
--- a/Solver/linearSystemPETSc.hpp
+++ b/Solver/linearSystemPETSc.hpp
@@ -163,6 +163,14 @@ template <class scalar> void linearSystemPETSc<scalar>::preAllocateEntries()
   }
   if(blockSize > 1) _check(MatSetOption(_a, MAT_ROW_ORIENTED, PETSC_FALSE));
   _entriesPreAllocated = true;
+
+#if ((PETSC_VERSION_MAJOR == 3) && (PETSC_VERSION_MINOR >= 3))
+  // Preallocation routines automatically set now
+  // MAT_NEW_NONZERO_ALLOCATION_ERR, which causes a problem when the mask of the
+  // matrix changes.  We must disable the error generation and allow new
+  // allocation (if needed)
+  _check(MatSetOption(_a, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
+#endif
 }
 
 template <class scalar> void linearSystemPETSc<scalar>::allocate(int nbRows)
@@ -219,6 +227,7 @@ template <class scalar> void linearSystemPETSc<scalar>::allocate(int nbRows)
   _localRowEnd = nbRows;
   _globalSize = _localSize;
 #endif
+
   // preallocation option must be set after other options
   _check(VecCreate(_comm, &_x));
   _check(VecSetSizes(_x, blockSize * nbRows, PETSC_DETERMINE));
diff --git a/api/gen.py b/api/gen.py
index a39122a6c5e5ec62d66707fad758a49b2193f1d5..b9c29ca0413eb6f6bb59dd8a41c3677b8a0c3a50 100644
--- a/api/gen.py
+++ b/api/gen.py
@@ -728,8 +728,11 @@ onelab = gmsh.add_module('logger','Message logger functions')
 doc = '''Write a `message'. `level' can be "info", "warning" or "error".'''
 onelab.add('write',doc,None,istring('message'),istring('level','"info"'))
 
-doc = '''Start logging messages in `log'.'''
-onelab.add('start',doc,None,ovectorstring('log'))
+doc = '''Start logging messages.'''
+onelab.add('start',doc,None)
+
+doc = '''Get logged messages.'''
+onelab.add('get',doc,None,ovectorstring('log'))
 
 doc = '''Stop logging messages.'''
 onelab.add('stop',doc,None)
diff --git a/api/gmsh.h b/api/gmsh.h
index a6afefb12e5651c29178e62e4c1631468b136c23..eecca92a01fb20d22c11012785707865d4e02846 100644
--- a/api/gmsh.h
+++ b/api/gmsh.h
@@ -1795,8 +1795,11 @@ namespace gmsh { // Top-level functions
     GMSH_API void write(const std::string & message,
                         const std::string & level = "info");
 
-    // Start logging messages in `log'.
-    GMSH_API void start(std::vector<std::string> & log);
+    // Start logging messages.
+    GMSH_API void start();
+
+    // Get logged messages.
+    GMSH_API void get(std::vector<std::string> & log);
 
     // Stop logging messages.
     GMSH_API void stop();
diff --git a/api/gmsh.h_cwrap b/api/gmsh.h_cwrap
index 3289824ff5614f4d49b2076f1ee2cfcf619c4ca7..71d8b6b510ba5d7c6082bdd503068c027cde9899 100644
--- a/api/gmsh.h_cwrap
+++ b/api/gmsh.h_cwrap
@@ -3349,12 +3349,20 @@ namespace gmsh { // Top-level functions
       if(ierr) throw ierr;
     }
 
-    // Start logging messages in `log'.
-    GMSH_API void start(std::vector<std::string> & log)
+    // Start logging messages.
+    GMSH_API void start()
+    {
+      int ierr = 0;
+      gmshLoggerStart(&ierr);
+      if(ierr) throw ierr;
+    }
+
+    // Get logged messages.
+    GMSH_API void get(std::vector<std::string> & log)
     {
       int ierr = 0;
       char **api_log_; size_t api_log_n_;
-      gmshLoggerStart(&api_log_, &api_log_n_, &ierr);
+      gmshLoggerGet(&api_log_, &api_log_n_, &ierr);
       if(ierr) throw ierr;
       log.resize(api_log_n_); for(size_t i = 0; i < api_log_n_; ++i){ log[i] = std::string(api_log_[i]); gmshFree(api_log_[i]); } gmshFree(api_log_);
     }
diff --git a/api/gmsh.jl b/api/gmsh.jl
index bbb96b8a798c954e99bfa164bc836f46aadebc3c..aeb6d3550d83f31d4bb265e8c82d04608e33cd00 100644
--- a/api/gmsh.jl
+++ b/api/gmsh.jl
@@ -4197,18 +4197,32 @@ end
 """
     gmsh.logger.start()
 
-Start logging messages in `log`.
+Start logging messages.
+"""
+function start()
+    ierr = Ref{Cint}()
+    ccall((:gmshLoggerStart, gmsh.lib), Nothing,
+          (Ptr{Cint},),
+          ierr)
+    ierr[] != 0 && error("gmshLoggerStart returned non-zero error code: $(ierr[])")
+    return nothing
+end
+
+"""
+    gmsh.logger.get()
+
+Get logged messages.
 
 Return `log`.
 """
-function start()
+function get()
     api_log_ = Ref{Ptr{Ptr{Cchar}}}()
     api_log_n_ = Ref{Csize_t}()
     ierr = Ref{Cint}()
-    ccall((:gmshLoggerStart, gmsh.lib), Nothing,
+    ccall((:gmshLoggerGet, gmsh.lib), Nothing,
           (Ptr{Ptr{Ptr{Cchar}}}, Ptr{Csize_t}, Ptr{Cint}),
           api_log_, api_log_n_, ierr)
-    ierr[] != 0 && error("gmshLoggerStart returned non-zero error code: $(ierr[])")
+    ierr[] != 0 && error("gmshLoggerGet returned non-zero error code: $(ierr[])")
     tmp_api_log_ = unsafe_wrap(Array, api_log_[], api_log_n_[], own=true)
     log = [unsafe_string(tmp_api_log_[i]) for i in 1:length(tmp_api_log_) ]
     return log
diff --git a/api/gmsh.py b/api/gmsh.py
index 02f1240628cb2c1472250027c83a6e7b675093a9..636d99df8b01bbeb5c3e8b591075d92125c619d3 100644
--- a/api/gmsh.py
+++ b/api/gmsh.py
@@ -4848,18 +4848,31 @@ class logger:
     @staticmethod
     def start():
         """
-        Start logging messages in `log'.
+        Start logging messages.
+        """
+        ierr = c_int()
+        lib.gmshLoggerStart(
+            byref(ierr))
+        if ierr.value != 0:
+            raise ValueError(
+                "gmshLoggerStart returned non-zero error code: ",
+                ierr.value)
+
+    @staticmethod
+    def get():
+        """
+        Get logged messages.
 
         Return `log'.
         """
         api_log_, api_log_n_ = POINTER(POINTER(c_char))(), c_size_t()
         ierr = c_int()
-        lib.gmshLoggerStart(
+        lib.gmshLoggerGet(
             byref(api_log_), byref(api_log_n_),
             byref(ierr))
         if ierr.value != 0:
             raise ValueError(
-                "gmshLoggerStart returned non-zero error code: ",
+                "gmshLoggerGet returned non-zero error code: ",
                 ierr.value)
         return _ovectorstring(api_log_, api_log_n_.value)
 
diff --git a/api/gmshc.cpp b/api/gmshc.cpp
index 365e152f4a32828a9b78ac287058a7124491d002..ef46efcd82b3073e1ccd360e4c1d2ba9c6a3eabd 100644
--- a/api/gmshc.cpp
+++ b/api/gmshc.cpp
@@ -2906,12 +2906,23 @@ GMSH_API void gmshLoggerWrite(const char * message, const char * level, int * ie
   }
 }
 
-GMSH_API void gmshLoggerStart(char *** log, size_t * log_n, int * ierr)
+GMSH_API void gmshLoggerStart(int * ierr)
+{
+  if(ierr) *ierr = 0;
+  try {
+    gmsh::logger::start();
+  }
+  catch(int api_ierr_){
+    if(ierr) *ierr = api_ierr_;
+  }
+}
+
+GMSH_API void gmshLoggerGet(char *** log, size_t * log_n, int * ierr)
 {
   if(ierr) *ierr = 0;
   try {
     std::vector<std::string> api_log_;
-    gmsh::logger::start(api_log_);
+    gmsh::logger::get(api_log_);
     vectorstring2charptrptr(api_log_, log, log_n);
   }
   catch(int api_ierr_){
diff --git a/api/gmshc.h b/api/gmshc.h
index 1ed8877d87ae6ce00e7ff17ce785398af490ee68..de7c228422f770c076db9a80d768eaab45378041 100644
--- a/api/gmshc.h
+++ b/api/gmshc.h
@@ -1913,9 +1913,12 @@ GMSH_API void gmshLoggerWrite(const char * message,
                               const char * level,
                               int * ierr);
 
-/* Start logging messages in `log'. */
-GMSH_API void gmshLoggerStart(char *** log, size_t * log_n,
-                              int * ierr);
+/* Start logging messages. */
+GMSH_API void gmshLoggerStart(int * ierr);
+
+/* Get logged messages. */
+GMSH_API void gmshLoggerGet(char *** log, size_t * log_n,
+                            int * ierr);
 
 /* Stop logging messages. */
 GMSH_API void gmshLoggerStop(int * ierr);
diff --git a/demos/api/t16.cpp b/demos/api/t16.cpp
index 18e342e3be410ffce4aba792e27aeb97349106ee..3de3680ffb4f6efacd3207f1408db41d8902b612 100644
--- a/demos/api/t16.cpp
+++ b/demos/api/t16.cpp
@@ -13,8 +13,7 @@ int main(int argc, char **argv)
 
   model::add("t16");
 
-  std::vector<std::string> log;
-  gmsh::logger::start(log);
+  gmsh::logger::start();
 
   std::vector<std::pair<int, int> > ov;
   std::vector<std::vector<std::pair<int, int> > > ovv;
@@ -52,8 +51,10 @@ int main(int argc, char **argv)
 
   gmsh::write("t16.msh");
 
-  gmsh::logger::stop();
+  std::vector<std::string> log;
+  gmsh::logger::get(log);
   std::cout << "Logger has recorded " << log.size() << " lines" << std::endl;
+  gmsh::logger::stop();
 
   gmsh::finalize();
   return 0;
diff --git a/doc/texinfo/version.texi b/doc/texinfo/version.texi
index 4d1cc26943510ea887799d86443c91bddbf2568a..ef63dd1928d42f7283cadbb2b4bab0a0e613ed04 100644
--- a/doc/texinfo/version.texi
+++ b/doc/texinfo/version.texi
@@ -1,3 +1,3 @@
 @c This file was generated by cmake: do not edit manually!
 
-@set GMSH-VERSION 4.1.5  (development version)
+@set GMSH-VERSION 4.2.0  (development version)