Browse Source

vfs: Show IOError instead of AssertionError if read_file fails

The methods are marked non-BLOCKING since the GIL needs to be held while throwing exceptions.  We handle the GIL in the extension functions instead.
rdb 8 years ago
parent
commit
c6dda2a44a

+ 2 - 2
panda/src/express/virtualFile.h

@@ -56,12 +56,12 @@ PUBLISHED:
   BLOCKING void ls(ostream &out = cout) const;
   BLOCKING void ls(ostream &out = cout) const;
   BLOCKING void ls_all(ostream &out = cout) const;
   BLOCKING void ls_all(ostream &out = cout) const;
 
 
-  EXTENSION(BLOCKING PyObject *read_file(bool auto_unwrap) const);
+  EXTENSION(PyObject *read_file(bool auto_unwrap) const);
   BLOCKING virtual istream *open_read_file(bool auto_unwrap) const;
   BLOCKING virtual istream *open_read_file(bool auto_unwrap) const;
   BLOCKING virtual void close_read_file(istream *stream) const;
   BLOCKING virtual void close_read_file(istream *stream) const;
   virtual bool was_read_successful() const;
   virtual bool was_read_successful() const;
 
 
-  EXTENSION(BLOCKING PyObject *write_file(PyObject *data, bool auto_wrap));
+  EXTENSION(PyObject *write_file(PyObject *data, bool auto_wrap));
   BLOCKING virtual ostream *open_write_file(bool auto_wrap, bool truncate);
   BLOCKING virtual ostream *open_write_file(bool auto_wrap, bool truncate);
   BLOCKING virtual ostream *open_append_file();
   BLOCKING virtual ostream *open_append_file();
   BLOCKING virtual void close_write_file(ostream *stream);
   BLOCKING virtual void close_write_file(ostream *stream);

+ 2 - 2
panda/src/express/virtualFileSystem.h

@@ -95,11 +95,11 @@ PUBLISHED:
 
 
   static VirtualFileSystem *get_global_ptr();
   static VirtualFileSystem *get_global_ptr();
 
 
-  EXTENSION(BLOCKING PyObject *read_file(const Filename &filename, bool auto_unwrap) const);
+  EXTENSION(PyObject *read_file(const Filename &filename, bool auto_unwrap) const);
   BLOCKING istream *open_read_file(const Filename &filename, bool auto_unwrap) const;
   BLOCKING istream *open_read_file(const Filename &filename, bool auto_unwrap) const;
   BLOCKING static void close_read_file(istream *stream);
   BLOCKING static void close_read_file(istream *stream);
 
 
-  EXTENSION(BLOCKING PyObject *write_file(const Filename &filename, PyObject *data, bool auto_wrap));
+  EXTENSION(PyObject *write_file(const Filename &filename, PyObject *data, bool auto_wrap));
   BLOCKING ostream *open_write_file(const Filename &filename, bool auto_wrap, bool truncate);
   BLOCKING ostream *open_write_file(const Filename &filename, bool auto_wrap, bool truncate);
   BLOCKING ostream *open_append_file(const Filename &filename);
   BLOCKING ostream *open_append_file(const Filename &filename);
   BLOCKING static void close_write_file(ostream *stream);
   BLOCKING static void close_write_file(ostream *stream);

+ 14 - 1
panda/src/express/virtualFileSystem_ext.cxx

@@ -26,9 +26,22 @@
  */
  */
 PyObject *Extension<VirtualFileSystem>::
 PyObject *Extension<VirtualFileSystem>::
 read_file(const Filename &filename, bool auto_unwrap) const {
 read_file(const Filename &filename, bool auto_unwrap) const {
+  // Release the GIL while we do this potentially slow operation.
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  PyThreadState *_save;
+  Py_UNBLOCK_THREADS
+#endif
+
   vector_uchar pv;
   vector_uchar pv;
   bool okflag = _this->read_file(filename, pv, auto_unwrap);
   bool okflag = _this->read_file(filename, pv, auto_unwrap);
-  nassertr(okflag, NULL);
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  Py_BLOCK_THREADS
+#endif
+
+  if (!okflag) {
+    return PyErr_Format(PyExc_IOError, "Failed to read file: '%s'", filename.c_str());
+  }
 
 
 #if PY_MAJOR_VERSION >= 3
 #if PY_MAJOR_VERSION >= 3
   if (pv.empty()) {
   if (pv.empty()) {

+ 26 - 1
panda/src/express/virtualFile_ext.cxx

@@ -26,9 +26,23 @@
  */
  */
 PyObject *Extension<VirtualFile>::
 PyObject *Extension<VirtualFile>::
 read_file(bool auto_unwrap) const {
 read_file(bool auto_unwrap) const {
+  // Release the GIL while we do this potentially slow operation.
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  PyThreadState *_save;
+  Py_UNBLOCK_THREADS
+#endif
+
   vector_uchar pv;
   vector_uchar pv;
   bool okflag = _this->read_file(pv, auto_unwrap);
   bool okflag = _this->read_file(pv, auto_unwrap);
-  nassertr(okflag, NULL);
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  Py_BLOCK_THREADS
+#endif
+
+  if (!okflag) {
+    Filename fn = _this->get_filename();
+    return PyErr_Format(PyExc_IOError, "Failed to read file: '%s'", fn.c_str());
+  }
 
 
 #if PY_MAJOR_VERSION >= 3
 #if PY_MAJOR_VERSION >= 3
   if (pv.empty()) {
   if (pv.empty()) {
@@ -68,7 +82,18 @@ write_file(PyObject *data, bool auto_wrap) {
   }
   }
 #endif
 #endif
 
 
+  // Release the GIL while we do this potentially slow operation.
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  PyThreadState *_save;
+  Py_UNBLOCK_THREADS
+#endif
+
   bool result = _this->write_file((const unsigned char *)buffer, length, auto_wrap);
   bool result = _this->write_file((const unsigned char *)buffer, length, auto_wrap);
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  Py_BLOCK_THREADS
+#endif
+
   return PyBool_FromLong(result);
   return PyBool_FromLong(result);
 }
 }