Changeset - r12087:0095f1069b29
[Not reviewed]
master
0 6 0
yexo - 15 years ago 2009-06-01 22:00:47
yexo@openttd.org
(svn r16502) -Fix [FS#2935]: when an AI was suspended while in a function called (indirectly) via call/acall/pcall OpenTTD crashed. Fix this by disallowing AIs to be suspended while called via call/acall/pcall.
IMPORTANT FOR AI WRITERS: AIs can no longer call any DoCommand functions (change anything, build vehicles, etc.) in a function called (indirectly) via call/acall/pcall. Where possible, please rewrite your code so it doesn't use call/acall/pcall
6 files changed with 24 insertions and 1 deletions:
0 comments (0 inline, 0 general)
src/3rdparty/squirrel/include/squirrel.h
Show inline comments
 
@@ -272,12 +272,13 @@ typedef struct tagSQRegFunction{
 
	SQFUNCTION f;
 
	SQInteger nparamscheck;
 
	const SQChar *typemask;
 
}SQRegFunction;
 

	
 
/*vm*/
 
SQUIRREL_API bool sq_can_suspend(HSQUIRRELVM v);
 
SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize);
 
SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize);
 
SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v);
 
SQUIRREL_API void sq_close(HSQUIRRELVM v);
 
SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p);
 
SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v);
src/3rdparty/squirrel/squirrel/sqapi.cpp
Show inline comments
 
@@ -87,12 +87,17 @@ SQInteger sq_getvmstate(HSQUIRRELVM v)
 
	else {
 
		if(v->_callsstacksize != 0) return SQ_VMSTATE_RUNNING;
 
		else return SQ_VMSTATE_IDLE;
 
	}
 
}
 

	
 
bool sq_can_suspend(HSQUIRRELVM v)
 
{
 
	return v->_can_suspend;
 
}
 

	
 
void sq_seterrorhandler(HSQUIRRELVM v)
 
{
 
	SQObject o = stack_get(v, -1);
 
	if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
 
		v->_errorhandler = o;
 
		v->Pop();
src/ai/ai_instance.hpp
Show inline comments
 
@@ -27,12 +27,13 @@ private:
 
	int time;
 
	AISuspendCallbackProc *callback;
 
};
 

	
 
class AIInstance {
 
public:
 
	friend class AIObject;
 
	AIInstance(class AIInfo *info);
 
	~AIInstance();
 

	
 
	/**
 
	 * An AI in multiplayer waits for the server to handle his DoCommand.
 
	 *  It keeps waiting for this until this function is called.
src/ai/api/ai_object.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/** @file ai_object.cpp Implementation of AIObject. */
 

	
 
#include "../../stdafx.h"
 
#include <squirrel.h>
 
#include "../../script/squirrel.hpp"
 
#include "../../company_base.h"
 

	
 
#include "ai_log.hpp"
 
#include "table/strings.h"
 
#include "../ai.hpp"
 
#include "../ai_storage.hpp"
 
#include "../ai_instance.hpp"
 
#include "ai_error.hpp"
 
@@ -155,13 +160,14 @@ void AIObject::SetAllowDoCommand(bool al
 
{
 
	GetStorage()->allow_do_command = allow;
 
}
 

	
 
bool AIObject::GetAllowDoCommand()
 
{
 
	return GetStorage()->allow_do_command;
 
	Squirrel *squirrel = Company::Get(_current_company)->ai_instance->engine;
 
	return GetStorage()->allow_do_command && squirrel->CanSuspend();
 
}
 

	
 
void *&AIObject::GetEventPointer()
 
{
 
	return GetStorage()->event_data;
 
}
src/script/squirrel.cpp
Show inline comments
 
@@ -505,6 +505,11 @@ bool Squirrel::HasScriptCrashed()
 
}
 

	
 
void Squirrel::ResetCrashed()
 
{
 
	this->crashed = false;
 
}
 

	
 
bool Squirrel::CanSuspend()
 
{
 
	return sq_can_suspend(this->vm);
 
}
src/script/squirrel.hpp
Show inline comments
 
@@ -210,9 +210,14 @@ public:
 
	bool HasScriptCrashed();
 

	
 
	/**
 
	 * Reset the crashed status.
 
	 */
 
	void ResetCrashed();
 

	
 
	/**
 
	 * Are we allowed to suspend the squirrel script at this moment?
 
	 */
 
	bool CanSuspend();
 
};
 

	
 
#endif /* SQUIRREL_HPP */
0 comments (0 inline, 0 general)