Browse Source

Warn instad of crashing when class instance is gone after yield. Closes #5247 , probably closes other yield related crashes

Juan Linietsky 9 years ago
parent
commit
36e754457f
3 changed files with 30 additions and 0 deletions
  1. 25 0
      modules/gdscript/gd_function.cpp
  2. 3 0
      modules/gdscript/gd_function.h
  3. 2 0
      modules/gdscript/gd_script.h

+ 25 - 0
modules/gdscript/gd_function.cpp

@@ -846,6 +846,8 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
 				gdfs->state._class=_class;
 				gdfs->state.ip=ip+ipofs;
 				gdfs->state.line=line;
+				gdfs->state.instance_id=(p_instance && p_instance->get_owner())?p_instance->get_owner()->get_instance_ID():0;
+				gdfs->state.script_id=_class->get_instance_ID();
 				//gdfs->state.result_pos=ip+ipofs-1;
 				gdfs->state.defarg=defarg;
 				gdfs->state.instance=p_instance;
@@ -1352,6 +1354,18 @@ GDFunction::~GDFunction()  {
 
 Variant GDFunctionState::_signal_callback(const Variant** p_args, int p_argcount, Variant::CallError& r_error) {
 
+#ifdef DEBUG_ENABLED
+	if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
+		ERR_EXPLAIN("Resumed after yield, but class instance is gone");
+		ERR_FAIL_V(Variant());
+	}
+
+	if (state.script_id && !ObjectDB::get_instance(state.script_id)) {
+		ERR_EXPLAIN("Resumed after yield, but script is gone");
+		ERR_FAIL_V(Variant());
+	}
+#endif
+
 	Variant arg;
 	r_error.error=Variant::CallError::CALL_OK;
 
@@ -1398,6 +1412,17 @@ bool GDFunctionState::is_valid() const {
 Variant GDFunctionState::resume(const Variant& p_arg) {
 
 	ERR_FAIL_COND_V(!function,Variant());
+#ifdef DEBUG_ENABLED
+	if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
+		ERR_EXPLAIN("Resumed after yield, but class instance is gone");
+		ERR_FAIL_V(Variant());
+	}
+
+	if (state.script_id && !ObjectDB::get_instance(state.script_id)) {
+		ERR_EXPLAIN("Resumed after yield, but script is gone");
+		ERR_FAIL_V(Variant());
+	}
+#endif
 
 	state.result=p_arg;
 	Variant::CallError err;

+ 3 - 0
modules/gdscript/gd_function.h

@@ -136,6 +136,9 @@ public:
 
 	struct CallState {
 
+		ObjectID instance_id; //by debug only
+		ObjectID script_id;
+
 		GDInstance *instance;
 		Vector<uint8_t> stack;
 		int stack_size;

+ 2 - 0
modules/gdscript/gd_script.h

@@ -202,6 +202,8 @@ friend class GDCompiler;
 
 public:
 
+	_FORCE_INLINE_ Object* get_owner() { return owner; }
+
 	virtual bool set(const StringName& p_name, const Variant& p_value);
 	virtual bool get(const StringName& p_name, Variant &r_ret) const;
 	virtual void get_property_list(List<PropertyInfo> *p_properties) const;