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;
}
////////////////////////////////////////////////////////////////////
// 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
// Access: Public

View File

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

View File

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

View File

@ -63,6 +63,12 @@ P3DHost::
}
}
_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;
PackageMap::iterator pi = package_map.find(key);
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 =
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;
}

View File

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

View File

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

View File

@ -129,8 +129,14 @@ P3DInstanceManager::
sigaction(SIGPIPE, &_old_sigpipe, NULL);
#endif // _WIN32
assert(_instances.empty());
// force-finish any remaining instances.
while (!_instances.empty()) {
P3DInstance *inst = *(_instances.begin());
finish_instance(inst);
}
assert(_sessions.empty());
assert(_instances.empty());
if (_auth_session != NULL) {
p3d_unref_delete(_auth_session);
@ -421,11 +427,12 @@ start_instance(P3DInstance *inst) {
////////////////////////////////////////////////////////////////////
void P3DInstanceManager::
finish_instance(P3DInstance *inst) {
nout << "finish_instance\n";
nout << "finish_instance: " << inst << "\n";
Instances::iterator ii;
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());
if (si != _sessions.end()) {
@ -442,9 +449,7 @@ finish_instance(P3DInstance *inst) {
}
inst->cleanup();
nout << "done cleanup, calling delete\n";
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;
}
////////////////////////////////////////////////////////////////////
// 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
// Access: Public
@ -1423,10 +1454,24 @@ do_step(bool download_finished) {
if (_download->get_download_success()) {
// The Download object has already validated the hash.
return IT_step_complete;
} 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 {
// The Download object has already tried all of the mirrors, and
// they all failed.

View File

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

View File

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

View File

@ -336,6 +336,7 @@ stop_outstanding_streams() {
NPStream *stream = (*si);
nout << "Stopping stream " << (void *)stream << "\n";
browser->destroystream(_npp_instance, stream, NPRES_USER_BREAK);
destroy_stream(stream, NPRES_USER_BREAK);
}
assert(_streams.empty());
@ -450,9 +451,7 @@ write_stream(NPStream *stream, int offset, int len, void *buffer) {
NPError PPInstance::
destroy_stream(NPStream *stream, NPReason reason) {
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);
}

View File

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