Index: trunk/include/VBox/settings.h
===================================================================
--- trunk/include/VBox/settings.h	(revision 8019)
+++ trunk/include/VBox/settings.h	(revision 8020)
@@ -81,4 +81,9 @@
  * Making deep copies or detaching the existing shallow copy from its original
  * is not yet supported.
+ *
+ * Note that the Settings File API is not thread-safe. It means that if you
+ * want to use the same instance of a class from the settings namespace on more
+ * than one thread at a time, you will have to provide necessary access
+ * serialization yourself.
  *
  * Due to some (not propely studied) libxml2 limitations, the Settings File
@@ -1171,5 +1176,12 @@
  * regular files.
  *
- * The File class uses IPRT File API for file operations.
+ * The File class uses IPRT File API for file operations. Note that IPRT File
+ * API is not thread-safe. This means that if you pass the same RTFILE handle to
+ * different File instances that may be simultaneously used on different
+ * threads, you should care about serialization; otherwise you will get garbage
+ * when reading from such File instances.
+ *
+ * @todo We should duplicate file handles (once this API is in IPRT) passed to
+ *       constructors to provide thread-safety.
  */
 class VBOXSETTINGS_CLASS File : public Input, public Output
@@ -1192,4 +1204,6 @@
     File (Mode aMode, const char *aFileName);
 
+#if 0
+    /// @todo disabled until made thread-safe by using handle duplicates
     /**
      * Uses the given file handle to perform file operations. The given file
@@ -1204,9 +1218,15 @@
      * this object destruction.
      *
+     * @note It you pass the same RTFILE handle to more than one File instance,
+     *       please make sure you have provided serialization in case if these
+     *       instasnces are to be simultaneously used by different threads.
+     *       Otherwise you may get garbage when reading or writing.
+     *
      * @param aHandle   Open file handle.
      * @param aMode     File mode of the open file handle.
-     * @param aFileName File name (for reference).
-     */
-    File (Mode aMode, RTFILE aHandle, const char *aFileName = NULL);
+     * @param aFileName File name (for reference, may be NULL).
+     */
+    File (Mode aMode, RTFILE aHandle, const char *aFileName);
+#endif
 
     /**
@@ -1282,4 +1302,18 @@
 /**
  * The XmlTreeBackend class uses XML markup to store settings trees.
+ *
+ * @note libxml2 and libxslt libraries used by the XmlTreeBackend are not
+ * fully reentrant. To "fix" this, the XmlTreeBackend backend serializes access
+ * to such non-reentrant parts using a global mutex so that only one thread can
+ * use non-reentrant code at a time. Currently, this relates to the #rawRead()
+ * method (and to #read() as a consequence). This menas that only one thread can
+ * parse an XML stream at a time; other threads trying to parse same or
+ * different streams using different XmlTreeBackend and Input instances
+ * will have to wait.
+ *
+ * Keep in mind that the above reentrancy fix does not imply thread-safety: it
+ * is still the caller's responsibility to provide serialization if the same
+ * XmlTreeBackend instnace (as well as instances of other classes from the
+ * settings namespace) needs to be used by more than one thread.
  */
 class VBOXSETTINGS_CLASS XmlTreeBackend : public TreeBackend
Index: trunk/src/VBox/Main/MachineImpl.cpp
===================================================================
--- trunk/src/VBox/Main/MachineImpl.cpp	(revision 8019)
+++ trunk/src/VBox/Main/MachineImpl.cpp	(revision 8020)
@@ -2032,6 +2032,11 @@
 
         /* load the config file */
+#if 0
+        /// @todo disabled until made thread-safe by using handle duplicates
         File file (File::ReadWrite, mData->mHandleCfgFile,
                    Utf8Str (mData->mConfigFileFull));
+#else
+        File file (File::Read, Utf8Str (mData->mConfigFileFull));
+#endif
         XmlTreeBackend tree;
 
@@ -2134,6 +2139,11 @@
 
         /* load the config file */
+#if 0
+        /// @todo disabled until made thread-safe by using handle duplicates
         File file (File::ReadWrite, mData->mHandleCfgFile,
                    Utf8Str (mData->mConfigFileFull));
+#else
+        File file (File::Read, Utf8Str (mData->mConfigFileFull));
+#endif
         XmlTreeBackend tree;
 
@@ -2207,6 +2217,11 @@
 
         /* load the config file */
+#if 0
+        /// @todo disabled until made thread-safe by using handle duplicates
         File file (File::ReadWrite, mData->mHandleCfgFile,
                    Utf8Str (mData->mConfigFileFull));
+#else
+        File file (File::ReadWrite, Utf8Str (mData->mConfigFileFull));
+#endif
         XmlTreeBackend tree;
 
@@ -4005,6 +4020,11 @@
         using namespace settings;
 
+#if 0
+        /// @todo disabled until made thread-safe by using handle duplicates
         File file (File::Read, mData->mHandleCfgFile,
                    Utf8Str (mData->mConfigFileFull));
+#else
+        File file (File::Read, Utf8Str (mData->mConfigFileFull));
+#endif
         XmlTreeBackend tree;
 
@@ -5141,6 +5161,11 @@
         using namespace settings;
 
+#if 0
+        /// @todo disabled until made thread-safe by using handle duplicates
         File file (File::ReadWrite, mData->mHandleCfgFile,
                    Utf8Str (mData->mConfigFileFull));
+#else
+        File file (File::ReadWrite, Utf8Str (mData->mConfigFileFull));
+#endif
         XmlTreeBackend tree;
 
@@ -5348,6 +5373,11 @@
 
         /* load the config file */
+#if 0
+        /// @todo disabled until made thread-safe by using handle duplicates
         File file (File::ReadWrite, mData->mHandleCfgFile,
                    Utf8Str (mData->mConfigFileFull));
+#else
+        File file (File::ReadWrite, Utf8Str (mData->mConfigFileFull));
+#endif
         XmlTreeBackend tree;
 
@@ -5925,6 +5955,11 @@
 
         /* load the config file */
+#if 0
+        /// @todo disabled until made thread-safe by using handle duplicates
         File file (File::ReadWrite, mData->mHandleCfgFile,
                    Utf8Str (mData->mConfigFileFull));
+#else
+        File file (File::ReadWrite, Utf8Str (mData->mConfigFileFull));
+#endif
         XmlTreeBackend tree;
 
Index: trunk/src/VBox/Main/VirtualBoxImpl.cpp
===================================================================
--- trunk/src/VBox/Main/VirtualBoxImpl.cpp	(revision 8019)
+++ trunk/src/VBox/Main/VirtualBoxImpl.cpp	(revision 8020)
@@ -206,5 +206,10 @@
             using namespace settings;
 
+#if 0
+            /// @todo disabled until made thread-safe by using handle duplicates
             File file (File::ReadWrite, mData.mCfgFile.mHandle, vboxConfigFile);
+#else
+            File file (File::Read, vboxConfigFile);
+#endif
             XmlTreeBackend tree;
 
@@ -1709,6 +1714,11 @@
 
         /* load the config file */
+#if 0
+        /// @todo disabled until made thread-safe by using handle duplicates
         File file (File::ReadWrite, mData.mCfgFile.mHandle,
                    Utf8Str (mData.mCfgFile.mName));
+#else
+        File file (File::Read, Utf8Str (mData.mCfgFile.mName));
+#endif
         XmlTreeBackend tree;
 
@@ -1807,6 +1817,11 @@
 
         /* load the config file */
+#if 0
+        /// @todo disabled until made thread-safe by using handle duplicates
         File file (File::ReadWrite, mData.mCfgFile.mHandle,
                    Utf8Str (mData.mCfgFile.mName));
+#else
+        File file (File::Read, Utf8Str (mData.mCfgFile.mName));
+#endif
         XmlTreeBackend tree;
 
@@ -1867,6 +1882,11 @@
 
         /* load the config file */
+#if 0
+        /// @todo disabled until made thread-safe by using handle duplicates
         File file (File::ReadWrite, mData.mCfgFile.mHandle,
                    Utf8Str (mData.mCfgFile.mName));
+#else
+        File file (File::ReadWrite, Utf8Str (mData.mCfgFile.mName));
+#endif
         XmlTreeBackend tree;
 
@@ -3721,6 +3741,11 @@
         using namespace settings;
 
+#if 0
+        /// @todo disabled until made thread-safe by using handle duplicates
         File file (File::ReadWrite, mData.mCfgFile.mHandle,
                    Utf8Str (mData.mCfgFile.mName));
+#else
+        File file (File::ReadWrite, Utf8Str (mData.mCfgFile.mName));
+#endif
         XmlTreeBackend tree;
 
Index: trunk/src/VBox/Main/xml/Settings.cpp
===================================================================
--- trunk/src/VBox/Main/xml/Settings.cpp	(revision 8019)
+++ trunk/src/VBox/Main/xml/Settings.cpp	(revision 8020)
@@ -21,4 +21,5 @@
 #include <iprt/err.h>
 #include <iprt/file.h>
+#include <iprt/lock.h>
 
 #include <libxml/tree.h>
@@ -74,4 +75,8 @@
     {
         xmlExternalEntityLoader defaultEntityLoader;
+
+        /** Used to provide some thread safety missing in libxml2 (see e.g.
+         *  XmlTreeBackend::read()) */
+        RTLockMtx lock;
     }
     xml;
@@ -382,5 +387,7 @@
 }
 
-File::File (Mode aMode, RTFILE aHandle, const char *aFileName /* = NULL */ )
+#if 0
+/// @todo disabled until made thread-safe by using handle duplicates
+File::File (Mode aMode, RTFILE aHandle, const char *aFileName)
     : m (new Data())
 {
@@ -400,4 +407,5 @@
     setPos (0);
 }
+#endif
 
 File::~File()
@@ -903,11 +911,12 @@
     m->trappedErr.reset();
 
-    /* Set up the external entity resolver. Note that we do it in a
-     * thread-unsafe fashion because this stuff is not thread-safe in libxml2.
-     * Making it thread-safe would require a) guarding this method with a
-     * mutex and b) requiring our API caller not to use libxml2 on some other
-     * thread (which is not practically possible). So, our API is not
-     * thread-safe for now (note that there are more thread-unsafe assumptions
-     * below like xsltGenericError which is also a libxslt limitation).*/
+    /* We use the global lock for the whole duration of this method to serialize
+     * access to thread-unsafe xmlGetExternalEntityLoader() and some other
+     * calls. It means that only one thread is able to parse an XML stream at a
+     * time but another choice would be to patch libxml2/libxslt which is
+     * unwanted now for several reasons. Search for "thread-safe" to find all
+     * unsafe cases. */
+    RTLock alock (gGlobal.xml.lock);
+
     xmlExternalEntityLoader oldEntityLoader = xmlGetExternalEntityLoader();
     sThat = this;
