소스 검색

fix a race condition, and detect some startup errors better

David Rose 16 년 전
부모
커밋
8e0aed64a7

+ 6 - 6
direct/src/p3d/PackageInfo.py

@@ -824,21 +824,21 @@ class PackageInfo:
         # there.  We have to take a bit of care to check if it's
         # already there, since there can be some ambiguity in
         # os-specific path strings.
-        root = self.packageDir.toOsSpecific()
+        osRoot = self.packageDir.toOsSpecific()
         foundOnPath = False
         for p in sys.path:
-            if root == p:
+            if osRoot == p:
                 # Already here, exactly.
                 foundOnPath = True
                 break
-            elif root == Filename.fromOsSpecific(p).toOsSpecific():
+            elif osRoot == Filename.fromOsSpecific(p).toOsSpecific():
                 # Already here, with some futzing.
                 foundOnPath = True
                 break
 
         if not foundOnPath:
             # Not already here; add it.
-            sys.path.append(root)
+            sys.path.append(osRoot)
 
         # Put it on the model-path, too.  We do this indiscriminantly,
         # because the Panda3D runtime won't be adding things to the
@@ -847,11 +847,11 @@ class PackageInfo:
 
         # Set the environment variable to reference the package root.
         envvar = '%s_ROOT' % (self.packageName.upper())
-        ExecutionEnvironment.setEnvironmentVariable(envvar, self.packageDir.toOsSpecific())
+        ExecutionEnvironment.setEnvironmentVariable(envvar, osRoot)
 
         # Now that the environment variable is set, read all of the
         # prc files in the package.
-        appRunner.loadMultifilePrcFiles(mf, root)
+        appRunner.loadMultifilePrcFiles(mf, self.packageDir)
 
         # Also, find any toplevel Python packages, and add these as
         # shared packages.  This will allow different packages

+ 20 - 10
direct/src/plugin/binaryXml.cxx

@@ -35,6 +35,19 @@ enum NodeType {
 static const size_t length_nonce1 = 812311453;
 static const size_t length_nonce2 = 612811373;
 
+////////////////////////////////////////////////////////////////////
+//     Function: init_xml
+//  Description: Should be called before spawning any threads to
+//               ensure the lock is initialized.
+////////////////////////////////////////////////////////////////////
+void
+init_xml() {
+  if (!xml_lock_initialized) {
+    INIT_LOCK(xml_lock);
+    xml_lock_initialized = true;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: write_xml_node
 //  Description: Recursively writes a node and all of its children to
@@ -254,9 +267,7 @@ read_xml_node(istream &in, char *&buffer, size_t &buffer_length,
 ////////////////////////////////////////////////////////////////////
 void
 write_xml(ostream &out, TiXmlDocument *doc, ostream &logfile) {
-  if (!xml_lock_initialized) {
-    INIT_LOCK(xml_lock);
-  }
+  assert(xml_lock_initialized);
   ACQUIRE_LOCK(xml_lock);
 
 #ifdef DO_BINARY_XML
@@ -301,10 +312,12 @@ write_xml(ostream &out, TiXmlDocument *doc, ostream &logfile) {
 ////////////////////////////////////////////////////////////////////
 TiXmlDocument *
 read_xml(istream &in, ostream &logfile) {
-  if (!xml_lock_initialized) {
-    INIT_LOCK(xml_lock);
-  }
-  ACQUIRE_LOCK(xml_lock);
+  // We don't acquire xml_lock while reading.  We can't, because our
+  // XML readers are all designed to block until data is available,
+  // and they can't block while holding the lock.
+
+  // Fortunately, there should be only one reader at a time, so a lock
+  // isn't really needed here.
 
 #if DO_BINARY_XML
   // binary read.
@@ -313,7 +326,6 @@ read_xml(istream &in, ostream &logfile) {
   TiXmlNode *xnode = read_xml_node(in, buffer, buffer_length, logfile);
   delete[] buffer;
   if (xnode == NULL) {
-    RELEASE_LOCK(xml_lock);
     return NULL;
   }
 
@@ -326,7 +338,6 @@ read_xml(istream &in, ostream &logfile) {
   in >> *doc;
   if (in.fail() || in.eof()) {
     delete doc;
-    RELEASE_LOCK(xml_lock);
     return NULL;
   }
 #endif
@@ -339,6 +350,5 @@ read_xml(istream &in, ostream &logfile) {
     logfile << logout.str() << flush;
   }
 
-  RELEASE_LOCK(xml_lock);
   return doc;
 }

+ 1 - 0
direct/src/plugin/binaryXml.h

@@ -26,6 +26,7 @@ using namespace std;
 // operators, but this is a smidge more efficient and gives us more
 // control.
 
+void init_xml();
 void write_xml(ostream &out, TiXmlDocument *doc, ostream &logfile);
 TiXmlDocument *read_xml(istream &in, ostream &logfile);
 

+ 3 - 0
direct/src/plugin/p3dInstanceManager.cxx

@@ -25,6 +25,7 @@
 #include "find_root_dir.h"
 #include "fileSpec.h"
 #include "get_tinyxml.h"
+#include "binaryXml.h"
 #include "mkdir_complete.h"
 
 // We can include this header file to get the DTOOL_PLATFORM
@@ -53,6 +54,8 @@ P3DInstanceManager *P3DInstanceManager::_global_ptr;
 ////////////////////////////////////////////////////////////////////
 P3DInstanceManager::
 P3DInstanceManager() {
+  init_xml();
+
   _is_initialized = false;
   _next_temp_filename_counter = 1;
   _unique_id = 0;

+ 13 - 0
direct/src/plugin/p3dPythonRun.cxx

@@ -41,6 +41,7 @@ P3DPythonRun(const char *program_name, const char *archive_file,
              FHandle input_handle, FHandle output_handle, 
              const char *log_pathname, bool interactive_console) {
   P3DWindowHandle::init_type();
+  init_xml();
 
   _read_thread_continue = false;
   _program_continue = true;
@@ -1179,6 +1180,9 @@ set_instance_info(P3DCInstance *inst, TiXmlElement *xinstance) {
 
   if (result == NULL) {
     PyErr_Print();
+    if (!_interactive_console) {
+      exit(1);
+    }
   }
   Py_XDECREF(result);
 }
@@ -1210,6 +1214,9 @@ add_package_info(P3DCInstance *inst, TiXmlElement *xpackage) {
 
   if (result == NULL) {
     PyErr_Print();
+    if (!_interactive_console) {
+      exit(1);
+    }
   }
   Py_XDECREF(result);
 }
@@ -1274,6 +1281,9 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
 
   if (result == NULL) {
     PyErr_Print();
+    if (!_interactive_console) {
+      exit(1);
+    }
   }
   Py_XDECREF(result);
 }
@@ -1370,6 +1380,9 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
 
   if (result == NULL) {
     PyErr_Print();
+    if (!_interactive_console) {
+      exit(1);
+    }
   }
   Py_XDECREF(result);
 }

+ 1 - 0
direct/src/plugin/p3dX11SplashWindow.cxx

@@ -260,6 +260,7 @@ start_subprocess() {
 
   if (child == 0) {
     // Here we are in the child process.
+    init_xml();
 
     // Open the read end of the pipe, and close the write end.
     _pipe_read.open_read(to_fd[0]);