better failed-case handling

This commit is contained in:
David Rose 2009-10-14 13:33:05 +00:00
parent 36d8b7c0f0
commit 9ecc675b72
10 changed files with 127 additions and 23 deletions

View File

@ -26,7 +26,7 @@ class coreapi(solo):
class images(package):
# The default startup images are stored as their own package.
names = ['download', 'play_click', 'play_ready', 'play_rollover',
names = ['download', 'failed', 'play_click', 'play_ready', 'play_rollover',
'auth_click', 'auth_ready', 'auth_rollover']
configDict = {}
for name in names:
@ -55,13 +55,12 @@ class images(package):
print "Could not locate %s" % (filename)
# Also make a few special cases. We use the same default image
# for download, ready, unauth, launch, and failed.
# for download, ready, unauth, and launch.
download = configDict.get('download_img', None)
if download:
configDict['ready_img'] = download
configDict['unauth_img'] = download
configDict['launch_img'] = download
configDict['failed_img'] = download
config(**configDict)

View File

@ -156,6 +156,7 @@ audio-library-name miles_audio
class audio(package):
# This package includes the best audio library for the given
# platform, assuming a non-commercial application.
require('panda3d')
if platform.startswith('osx'):
require('fmod')

View File

@ -107,6 +107,17 @@ is_started() const {
return (_session != NULL);
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::is_failed
// Access: Public
// Description: Returns true if this instance has tried and failed to
// launch for some reason.
////////////////////////////////////////////////////////////////////
inline bool P3DInstance::
is_failed() const {
return _failed;
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::ImageFile::Constructor
// Access: Public

View File

@ -93,11 +93,13 @@ P3DInstance(P3D_request_ready_func *func,
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
_instance_id = inst_mgr->get_unique_id();
_has_log_basename = false;
_hidden = (_fparams.lookup_token_int("hidden") != 0);
_allow_python_dev = false;
_keep_user_env = false;
_auto_start = false;
_auth_button_approved = false;
_failed = false;
_session = NULL;
_auth_session = NULL;
_panda3d = NULL;
@ -320,6 +322,7 @@ set_p3d_filename(const string &p3d_filename) {
if (!_mf_reader.open_read(_fparams.get_p3d_filename())) {
nout << "Couldn't read " << _fparams.get_p3d_filename() << "\n";
set_failed();
return;
}
@ -1189,6 +1192,9 @@ void P3DInstance::
mark_p3d_untrusted() {
// Failed test.
nout << "p3d untrusted\n";
if (is_failed()) {
return;
}
if (_p3dcert_package == NULL) {
// We have to go download this package.
@ -1238,7 +1244,7 @@ mark_p3d_trusted() {
stringstream sstream;
if (!_mf_reader.extract_one(sstream, "p3d_info.xml")) {
nout << "No p3d_info.xml file found in " << _fparams.get_p3d_filename() << "\n";
// TODO: fail.
set_failed();
} else {
sstream.seekg(0);
@ -1296,8 +1302,10 @@ scan_app_desc_file(TiXmlDocument *doc) {
_xpackage = (TiXmlElement *)xpackage->Clone();
const char *log_basename = _xpackage->Attribute("log_basename");
_has_log_basename = false;
if (log_basename != NULL) {
_log_basename = log_basename;
_has_log_basename = false;
}
TiXmlElement *xconfig = _xpackage->FirstChildElement("config");
@ -1675,6 +1683,21 @@ handle_script_request(const string &operation, P3D_object *object,
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::set_failed
// Access: Private
// Description: Sets the "failed" indication to display sadness to
// the user--we're unable to launch the instance for
// some reason.
////////////////////////////////////////////////////////////////////
void P3DInstance::
set_failed() {
_failed = true;
set_button_image(IT_none);
set_background_image(IT_failed);
make_splash_window();
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::make_splash_window
// Access: Private
@ -1698,6 +1721,12 @@ make_splash_window() {
make_visible = false;
}
if (_failed) {
// But, if we've failed to launch somehow, we need to let the user
// know.
make_visible = true;
}
if (_splash_window != NULL) {
// Already got one.
_splash_window->set_visible(make_visible);
@ -1929,7 +1958,7 @@ start_next_download() {
while (_download_package_index < (int)_downloading_packages.size()) {
P3DPackage *package = _downloading_packages[_download_package_index];
if (package->get_failed()) {
// Too bad. TODO: fail.
set_failed();
return;
}
@ -2001,8 +2030,8 @@ mark_download_complete() {
////////////////////////////////////////////////////////////////////
void P3DInstance::
ready_to_start() {
if (is_started()) {
// Already started.
if (is_started() || is_failed()) {
// Already started--or never mind.
return;
}
@ -2160,7 +2189,7 @@ report_package_done(P3DPackage *package, bool success) {
report_package_progress(package, 1.0);
start_next_download();
} else {
// TODO: fail.
set_failed();
}
}

View File

@ -99,6 +99,7 @@ public:
inline bool is_trusted() const;
void start_download(P3DDownload *download);
inline bool is_started() const;
inline bool is_failed() const;
void request_stop_sub_thread();
void request_stop_main_thread();
void request_refresh();
@ -164,6 +165,7 @@ private:
const string &property_name, P3D_object *value,
bool needs_response, int unique_id);
void set_failed();
void make_splash_window();
void set_background_image(ImageType image_type);
void set_button_image(ImageType image_type);
@ -226,11 +228,13 @@ private:
int _instance_id;
string _session_key;
string _log_basename;
bool _has_log_basename;
bool _hidden;
bool _allow_python_dev;
bool _keep_user_env;
bool _auto_start;
bool _auth_button_approved;
bool _failed;
P3DSession *_session;
P3DAuthSession *_auth_session;

View File

@ -222,17 +222,18 @@ initialize(const string &contents_filename, const string &host_url,
_log_basename = P3D_PLUGIN_LOG_BASENAME2;
}
#endif
if (!_log_basename.empty()) {
_log_pathname = _log_directory;
_log_pathname += _log_basename;
_log_pathname += ".log";
logfile.clear();
logfile.open(_log_pathname.c_str(), ios::out | ios::trunc);
if (logfile) {
logfile.setf(ios::unitbuf);
nout_stream = &logfile;
}
if (_log_basename.empty()) {
_log_basename = "p3dcore";
}
_log_pathname = _log_directory;
_log_pathname += _log_basename;
_log_pathname += ".log";
logfile.clear();
logfile.open(_log_pathname.c_str(), ios::out | ios::trunc);
if (logfile) {
logfile.setf(ios::unitbuf);
nout_stream = &logfile;
}
// Determine the temporary directory.
@ -434,6 +435,11 @@ set_p3d_filename(P3DInstance *inst, bool is_local,
////////////////////////////////////////////////////////////////////
bool P3DInstanceManager::
start_instance(P3DInstance *inst) {
if (inst->is_failed()) {
// Don't bother trying again.
return false;
}
if (inst->is_started()) {
// Already started.
return true;

View File

@ -90,6 +90,7 @@ set_wparams(const P3DWindowParams &wparams) {
EventTypeSpec list1[] = {
{ kEventClassWindow, kEventWindowDrawContent },
{ kEventClassWindow, kEventWindowBoundsChanged },
{ kEventClassWindow, kEventWindowClose },
{ kEventClassMouse, kEventMouseUp },
{ kEventClassMouse, kEventMouseDown },
{ kEventClassMouse, kEventMouseMoved },
@ -605,6 +606,12 @@ event_callback(EventHandlerCallRef my_handler, EventRef event) {
case kEventWindowDrawContent:
paint_window();
break;
case kEventWindowClose:
// When the user closes the splash window, stop the instance.
_inst->request_stop_sub_thread();
break;
};
break;

View File

@ -56,6 +56,8 @@ P3DSession(P3DInstance *inst) {
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
_session_id = inst_mgr->get_unique_id();
_session_key = inst->get_session_key();
_keep_user_env = false;
_failed = false;
_start_dir = inst_mgr->get_root_dir() + "/start";
_p3dpython_one_process = false;
@ -214,6 +216,10 @@ void P3DSession::
start_instance(P3DInstance *inst) {
assert(inst->_session == NULL);
assert(inst->get_session_key() == _session_key);
if (_failed) {
inst->set_failed();
return;
}
inst->ref();
ACQUIRE_LOCK(_instances_lock);
@ -342,6 +348,7 @@ command_and_response(TiXmlDocument *command) {
// in recursively.
_response_ready.release();
Instances::iterator ii;
// TODO: should we acquire _instances_lock? Deadlock concerns?
for (ii = _instances.begin(); ii != _instances.end(); ++ii) {
P3DInstance *inst = (*ii).second;
inst->bake_requests();
@ -678,6 +685,7 @@ start_p3dpython(P3DInstance *inst) {
if (inst->_panda3d == NULL) {
nout << "Couldn't start Python: no panda3d dependency.\n";
set_failed();
return;
}
@ -823,7 +831,7 @@ start_p3dpython(P3DInstance *inst) {
const char *dont_keep[] = {
"PATH", "LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH",
"PYTHONPATH", "PYTHONHOME", "PRC_PATH", "PANDA_PRC_PATH",
"TEMP",
"TEMP", "CTPROJS",
NULL
};
@ -931,19 +939,24 @@ start_p3dpython(P3DInstance *inst) {
// Get the log filename from the p3d_info.xml file.
string log_basename = inst->_log_basename;
bool has_log_basename = inst->_has_log_basename;
// But we also let it be overridden by the tokens.
if (inst->get_fparams().has_token("log_basename")) {
log_basename = inst->get_fparams().lookup_token("log_basename");
has_log_basename = true;
}
if (!has_log_basename) {
#ifdef P3D_PLUGIN_LOG_BASENAME3
if (log_basename.empty()) {
// No log_basename specified for the app; use the compiled-in
// default.
log_basename = P3D_PLUGIN_LOG_BASENAME3;
}
#endif
if (log_basename.empty()) {
log_basename = "p3dsession";
}
}
// However, it is always written into the log directory only; the
// user may not override the log file to put it anywhere else.
@ -975,6 +988,7 @@ start_p3dpython(P3DInstance *inst) {
// Create the pipe to the process.
if (!CreatePipe(&r_to, &w_to, NULL, 0)) {
nout << "failed to create pipe\n";
set_failed();
} else {
// Make sure the right end of the pipe is inheritable.
SetHandleInformation(r_to, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
@ -984,6 +998,7 @@ start_p3dpython(P3DInstance *inst) {
// Create the pipe from the process.
if (!CreatePipe(&r_from, &w_from, NULL, 0)) {
nout << "failed to create pipe\n";
set_failed();
} else {
// Make sure the right end of the pipe is inheritable.
SetHandleInformation(w_from, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
@ -1000,10 +1015,12 @@ start_p3dpython(P3DInstance *inst) {
int to_fd[2];
if (pipe(to_fd) < 0) {
perror("failed to create pipe");
set_failed();
}
int from_fd[2];
if (pipe(from_fd) < 0) {
perror("failed to create pipe");
set_failed();
}
_input_handle = to_fd[0];
@ -1012,6 +1029,10 @@ start_p3dpython(P3DInstance *inst) {
_pipe_write.open_write(to_fd[1]);
#endif // _WIN32
if (_failed) {
return;
}
// Get the filename of the Panda3D multifile. We need to pass this
// to p3dpython.
_mf_filename = inst->_panda3d->get_archive_file_pathname();
@ -1074,6 +1095,30 @@ start_p3dpython(P3DInstance *inst) {
_commands.clear();
}
////////////////////////////////////////////////////////////////////
// Function: P3DSession::set_failed
// Access: Private
// Description: Sets the "failed" indication to display sadness to
// the user--we're unable to launch the instance for
// some reason.
//
// When this is called on the P3DSession instead of on a
// particular P3DInstance, it means that all instances
// attached to this session are marked failed.
////////////////////////////////////////////////////////////////////
void P3DSession::
set_failed() {
_failed = true;
Instances::iterator ii;
ACQUIRE_LOCK(_instances_lock);
for (ii = _instances.begin(); ii != _instances.end(); ++ii) {
P3DInstance *inst = (*ii).second;
inst->set_failed();
}
RELEASE_LOCK(_instances_lock);
}
////////////////////////////////////////////////////////////////////
// Function: P3DSession::spawn_read_thread
// Access: Private

View File

@ -64,6 +64,7 @@ public:
private:
void start_p3dpython(P3DInstance *inst);
void set_failed();
void spawn_read_thread();
void join_read_thread();
@ -93,6 +94,7 @@ private:
string _python_root_dir;
string _start_dir;
bool _keep_user_env;
bool _failed;
// This information is passed to create_process(), or to
// p3dpython_thread_run().

View File

@ -152,7 +152,7 @@ run(int argc, char *argv[]) {
case 'l':
_log_dirname = Filename::from_os_specific(optarg).to_os_specific();
_log_basename = "panda3d";
_log_basename = "p3dcore";
break;
case 'i':