Browse Source

reload crashes

David Rose 16 years ago
parent
commit
93726b88c1

+ 22 - 0
direct/src/plugin/p3dDownload.I

@@ -23,6 +23,28 @@ get_url() const {
   return _url;
   return _url;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DDownload::set_instance
+//       Access: Public
+//  Description: Specifies the particular P3DInstance that is
+//               responsible for downloading this object.
+////////////////////////////////////////////////////////////////////
+inline void P3DDownload::
+set_instance(P3DInstance *instance) {
+  _instance = instance;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DDownload::get_instance
+//       Access: Public
+//  Description: Returns the particular P3DInstance that is
+//               responsible for downloading this object.
+////////////////////////////////////////////////////////////////////
+inline P3DInstance *P3DDownload::
+get_instance() const {
+  return _instance;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DDownload::get_download_progress
 //     Function: P3DDownload::get_download_progress
 //       Access: Public
 //       Access: Public

+ 2 - 0
direct/src/plugin/p3dDownload.cxx

@@ -30,6 +30,7 @@ P3DDownload() {
   
   
   _canceled = false;
   _canceled = false;
   _download_id = 0;
   _download_id = 0;
+  _instance = NULL;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -50,6 +51,7 @@ P3DDownload(const P3DDownload &copy) :
   
   
   _canceled = false;
   _canceled = false;
   _download_id = 0;
   _download_id = 0;
+  _instance = NULL;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 5 - 0
direct/src/plugin/p3dDownload.h

@@ -17,6 +17,7 @@
 
 
 #include "p3d_plugin_common.h"
 #include "p3d_plugin_common.h"
 #include "p3dReferenceCount.h"
 #include "p3dReferenceCount.h"
+class P3DInstance;
 
 
 #include <time.h>
 #include <time.h>
 
 
@@ -37,6 +38,9 @@ public:
   void set_url(const string &url);
   void set_url(const string &url);
   inline const string &get_url() const;
   inline const string &get_url() const;
 
 
+  inline void set_instance(P3DInstance *instance);
+  inline P3DInstance *get_instance() const;
+
   inline double get_download_progress() const;
   inline double get_download_progress() const;
   inline bool is_download_progress_known() const;
   inline bool is_download_progress_known() const;
   inline bool get_download_finished() const;
   inline bool get_download_finished() const;
@@ -78,6 +82,7 @@ private:
   bool _canceled;
   bool _canceled;
   int _download_id;
   int _download_id;
   string _url;
   string _url;
+  P3DInstance *_instance;
 };
 };
 
 
 #include "p3dDownload.I"
 #include "p3dDownload.I"

+ 17 - 3
direct/src/plugin/p3dHost.cxx

@@ -63,6 +63,12 @@ P3DHost::
     }
     }
   }
   }
   _packages.clear();
   _packages.clear();
+
+  FailedPackages::iterator pi;
+  for (pi = _failed_packages.begin(); pi != _failed_packages.end(); ++pi) {
+    delete (*pi);
+  }
+  _failed_packages.clear();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -285,13 +291,21 @@ get_package(const string &package_name, const string &package_version,
   string key = package_name + "_" + package_version;
   string key = package_name + "_" + package_version;
   PackageMap::iterator pi = package_map.find(key);
   PackageMap::iterator pi = package_map.find(key);
   if (pi != package_map.end()) {
   if (pi != package_map.end()) {
-    return (*pi).second;
+    P3DPackage *package = (*pi).second;
+    if (!package->get_failed()) {
+      return package;
+    }
+
+    // If the package has previously failed, move it aside and try
+    // again (maybe it just failed because the user interrupted it).
+    nout << "Package " << key << " has previously failed; trying again.\n";
+    _failed_packages.push_back(package);
+    (*pi).second = NULL;
   }
   }
 
 
   P3DPackage *package = 
   P3DPackage *package = 
     new P3DPackage(this, package_name, package_version, alt_host);
     new P3DPackage(this, package_name, package_version, alt_host);
-  bool inserted = package_map.insert(PackageMap::value_type(key, package)).second;
-  assert(inserted);
+  package_map[key] = package;
 
 
   return package;
   return package;
 }
 }

+ 2 - 0
direct/src/plugin/p3dHost.h

@@ -91,6 +91,8 @@ private:
   typedef map<string, P3DPackage *> PackageMap;
   typedef map<string, P3DPackage *> PackageMap;
   typedef map<string, PackageMap> Packages;
   typedef map<string, PackageMap> Packages;
   Packages _packages;
   Packages _packages;
+  typedef vector<P3DPackage *> FailedPackages;
+  FailedPackages _failed_packages;
 
 
   friend class P3DInstanceManager;
   friend class P3DInstanceManager;
 };
 };

+ 8 - 0
direct/src/plugin/p3dInstance.cxx

@@ -269,6 +269,9 @@ P3DInstance::
   Downloads::iterator di;
   Downloads::iterator di;
   for (di = _downloads.begin(); di != _downloads.end(); ++di) {
   for (di = _downloads.begin(); di != _downloads.end(); ++di) {
     P3DDownload *download = (*di).second;
     P3DDownload *download = (*di).second;
+    if (download->get_instance() == this) {
+      download->set_instance(NULL);
+    }
     p3d_unref_delete(download);
     p3d_unref_delete(download);
   }
   }
   _downloads.clear();
   _downloads.clear();
@@ -880,12 +883,16 @@ feed_url_stream(int unique_id,
   }
   }
 
 
   P3DDownload *download = (*di).second;
   P3DDownload *download = (*di).second;
+  assert(download->get_instance() == this);
   bool download_ok = download->feed_url_stream
   bool download_ok = download->feed_url_stream
     (result_code, http_status_code, total_expected_data,
     (result_code, http_status_code, total_expected_data,
      this_data, this_data_size);
      this_data, this_data_size);
 
 
   if (!download_ok || download->get_download_finished()) {
   if (!download_ok || download->get_download_finished()) {
     // All done.
     // All done.
+    if (download->get_instance() == this) {
+      download->set_instance(NULL);
+    }
     _downloads.erase(di);
     _downloads.erase(di);
     p3d_unref_delete(download);
     p3d_unref_delete(download);
   }
   }
@@ -1128,6 +1135,7 @@ start_download(P3DDownload *download, bool add_request) {
 
 
   int download_id = inst_mgr->get_unique_id();
   int download_id = inst_mgr->get_unique_id();
   download->set_download_id(download_id);
   download->set_download_id(download_id);
+  download->set_instance(this);
 
 
   download->ref();
   download->ref();
   bool inserted = _downloads.insert(Downloads::value_type(download_id, download)).second;
   bool inserted = _downloads.insert(Downloads::value_type(download_id, download)).second;

+ 11 - 6
direct/src/plugin/p3dInstanceManager.cxx

@@ -129,8 +129,14 @@ P3DInstanceManager::
   sigaction(SIGPIPE, &_old_sigpipe, NULL);
   sigaction(SIGPIPE, &_old_sigpipe, NULL);
 #endif  // _WIN32
 #endif  // _WIN32
 
 
-  assert(_instances.empty());
+  // force-finish any remaining instances.
+  while (!_instances.empty()) {
+    P3DInstance *inst = *(_instances.begin());
+    finish_instance(inst);
+  }
+
   assert(_sessions.empty());
   assert(_sessions.empty());
+  assert(_instances.empty());
 
 
   if (_auth_session != NULL) {
   if (_auth_session != NULL) {
     p3d_unref_delete(_auth_session);
     p3d_unref_delete(_auth_session);
@@ -421,11 +427,12 @@ start_instance(P3DInstance *inst) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DInstanceManager::
 void P3DInstanceManager::
 finish_instance(P3DInstance *inst) {
 finish_instance(P3DInstance *inst) {
-  nout << "finish_instance\n";
+  nout << "finish_instance: " << inst << "\n";
   Instances::iterator ii;
   Instances::iterator ii;
   ii = _instances.find(inst);
   ii = _instances.find(inst);
-  assert(ii != _instances.end());
-  _instances.erase(ii);
+  if (ii != _instances.end()) {
+    _instances.erase(ii);
+  }
 
 
   Sessions::iterator si = _sessions.find(inst->get_session_key());
   Sessions::iterator si = _sessions.find(inst->get_session_key());
   if (si != _sessions.end()) {
   if (si != _sessions.end()) {
@@ -442,9 +449,7 @@ finish_instance(P3DInstance *inst) {
   }
   }
 
 
   inst->cleanup();
   inst->cleanup();
-  nout << "done cleanup, calling delete\n";
   p3d_unref_delete(inst);
   p3d_unref_delete(inst);
-  nout << "done finish_instance\n";
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 48 - 3
direct/src/plugin/p3dPackage.cxx

@@ -1197,6 +1197,37 @@ is_extractable(FileSpec &file, const string &filename) const {
   return false;
   return false;
 }
 }
 
 
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DPackage::instance_terminating
+//       Access: Private
+//  Description: Called when P3D_RC_shutdown is received by any
+//               Download object, which indicates that the instance
+//               owning this download object is terminating and we
+//               should either find a new instance or abort the
+//               download.
+//
+//               The return value is true if a new instance is
+//               available, or false if not.
+////////////////////////////////////////////////////////////////////
+bool P3DPackage::
+instance_terminating(P3DInstance *instance) {
+  if (_instances.empty() ||
+      (_instances.size() == 1 && instance == _instances[0])) {
+    // No other instances.
+    return false;
+  }
+
+  // There are more instances available to continue this download;
+  // pick one of them.  Move this one to the end of the list.
+  Instances::iterator ii = find(_instances.begin(), _instances.end(), instance);
+  if (ii != _instances.end()) {
+    _instances.erase(ii);
+    _instances.push_back(instance);
+  }
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DPackage::Download::Constructor
 //     Function: P3DPackage::Download::Constructor
 //       Access: Public
 //       Access: Public
@@ -1423,10 +1454,24 @@ do_step(bool download_finished) {
   if (_download->get_download_success()) {
   if (_download->get_download_success()) {
     // The Download object has already validated the hash.
     // The Download object has already validated the hash.
     return IT_step_complete;
     return IT_step_complete;
+
   } else if (_download->get_download_terminated()) {
   } else if (_download->get_download_terminated()) {
-    // The download was interrupted because we're shutting down.
-    // Don't try any other plans.
-    return IT_terminate;
+    // The download was interrupted because its instance is shutting
+    // down.  Don't try any other plans, unless we have some more
+    // instances.
+    P3DInstance *instance = _download->get_instance();
+    if (!_package->instance_terminating(instance)) {
+      // That was the only instance referencing this package, so stop
+      // the download.
+      nout << "Terminating download of " << _urlbase << "\n";
+      return IT_terminate;
+    }
+    nout << "Restarting download of " << _urlbase << " on new instance\n";
+
+    p3d_unref_delete(_download);
+    _download = NULL;
+    return IT_continue;
+
   } else {
   } else {
     // The Download object has already tried all of the mirrors, and
     // The Download object has already tried all of the mirrors, and
     // they all failed.
     // they all failed.

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

@@ -213,6 +213,7 @@ private:
   void set_saved_download(Download *download);
   void set_saved_download(Download *download);
 
 
   bool is_extractable(FileSpec &file, const string &filename) const;
   bool is_extractable(FileSpec &file, const string &filename) const;
+  bool instance_terminating(P3DInstance *instance);
 
 
 public:
 public:
   class RequiredPackage {
   class RequiredPackage {

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

@@ -86,6 +86,7 @@ P3D_initialize(int api_version, const char *contents_filename,
 
 
 void 
 void 
 P3D_finalize() {
 P3D_finalize() {
+  nout << "P3D_finalize called\n";
   P3DInstanceManager::delete_global_ptr();
   P3DInstanceManager::delete_global_ptr();
 }
 }
 
 

+ 2 - 3
direct/src/plugin_npapi/ppInstance.cxx

@@ -336,6 +336,7 @@ stop_outstanding_streams() {
     NPStream *stream = (*si);
     NPStream *stream = (*si);
     nout << "Stopping stream " << (void *)stream << "\n";
     nout << "Stopping stream " << (void *)stream << "\n";
     browser->destroystream(_npp_instance, stream, NPRES_USER_BREAK);
     browser->destroystream(_npp_instance, stream, NPRES_USER_BREAK);
+    destroy_stream(stream, NPRES_USER_BREAK);
   }
   }
 
 
   assert(_streams.empty());
   assert(_streams.empty());
@@ -450,9 +451,7 @@ write_stream(NPStream *stream, int offset, int len, void *buffer) {
 NPError PPInstance::
 NPError PPInstance::
 destroy_stream(NPStream *stream, NPReason reason) {
 destroy_stream(NPStream *stream, NPReason reason) {
   Streams::iterator si = find(_streams.begin(), _streams.end(), stream);
   Streams::iterator si = find(_streams.begin(), _streams.end(), stream);
-  if (si == _streams.end()) {
-    nout << "Got destroy_stream for unknown stream\n";
-  } else {
+  if (si != _streams.end()) {
     _streams.erase(si);
     _streams.erase(si);
   }
   }
 
 

+ 5 - 5
direct/src/plugin_npapi/startup.cxx

@@ -418,10 +418,11 @@ NPP_SetWindow(NPP instance, NPWindow *window) {
 NPError
 NPError
 NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, 
 NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, 
               NPBool seekable, uint16_t *stype) {
               NPBool seekable, uint16_t *stype) {
-  nout << "NewStream " << type << ", " << stream->url 
-       << ", " << stream->end 
+  nout << "NewStream " << type << ": " << (void *)stream
+       << ", " << stream->url << ", size = " << stream->end 
        << ", notifyData = " << stream->notifyData
        << ", notifyData = " << stream->notifyData
-       << "\n";
+       << ", for " << instance 
+       << ", " << (PPInstance *)(instance->pdata) << "\n";
   PPInstance::generic_browser_call();
   PPInstance::generic_browser_call();
   PPInstance *inst = (PPInstance *)(instance->pdata);
   PPInstance *inst = (PPInstance *)(instance->pdata);
   assert(inst != NULL);
   assert(inst != NULL);
@@ -436,8 +437,7 @@ NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream,
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NPError 
 NPError 
 NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) {
 NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) {
-  nout << "DestroyStream " << stream->url 
-       << ", " << stream->end 
+  nout << "DestroyStream: " << (void *)stream << ", " << stream->url 
        << ", notifyData = " << stream->notifyData
        << ", notifyData = " << stream->notifyData
        << ", reason = " << reason
        << ", reason = " << reason
        << ", for " << instance 
        << ", for " << instance