reload crashes

This commit is contained in:
David Rose 2009-12-31 02:16:24 +00:00
parent 52b1a2af67
commit 93726b88c1
12 changed files with 124 additions and 20 deletions

View File

@ -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

View File

@ -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;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -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"

View File

@ -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; package_map[key] = package;
assert(inserted);
return package; return package;
} }

View File

@ -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;
}; };

View File

@ -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;

View File

@ -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()); if (ii != _instances.end()) {
_instances.erase(ii); _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";
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -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. // The download was interrupted because its instance is shutting
// Don't try any other plans. // down. Don't try any other plans, unless we have some more
return IT_terminate; // 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.

View File

@ -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 {

View File

@ -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();
} }

View File

@ -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()) { if (si != _streams.end()) {
nout << "Got destroy_stream for unknown stream\n";
} else {
_streams.erase(si); _streams.erase(si);
} }

View File

@ -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 nout << "NewStream " << type << ": " << (void *)stream
<< ", " << stream->end << ", " << 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 nout << "DestroyStream: " << (void *)stream << ", " << stream->url
<< ", " << stream->end
<< ", notifyData = " << stream->notifyData << ", notifyData = " << stream->notifyData
<< ", reason = " << reason << ", reason = " << reason
<< ", for " << instance << ", for " << instance