Skip to content

Commit

Permalink
Fixed Program.CallFunction so that it propagates python exceptions co…
Browse files Browse the repository at this point in the history
…rrectly to parent tasks (because this was broken, failures in function calls were sometimes ignored)

When loading managed scripts into a process or unloading them from a process we now perform the operation as a background task so that a failure in one script does not prevent the loading of other scripts
  • Loading branch information
kg committed Nov 28, 2010
1 parent 173f7cd commit 69afd43
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 26 deletions.
12 changes: 6 additions & 6 deletions ErrorDialog.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 41 additions & 17 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@
using Squared.Util.Event;

namespace ShootBlues {
public class PythonException : Exception {
public ProcessInfo Process;

public PythonException (ProcessInfo process, string traceback)
: base(traceback) {
Process = process;
}
}

public class ScriptName {
public readonly string Name;
public readonly string DefaultSearchPath;
Expand Down Expand Up @@ -291,7 +300,12 @@ private static SQLiteConnection OpenDatabase () {
}

private static bool OnTaskError (Exception error) {
ShowErrorMessage(error.ToString());
var pye = error as PythonException;

if (pye != null)
ShowErrorMessage(pye.Message, pye.Process);
else
ShowErrorMessage(error.ToString());

return true;
}
Expand Down Expand Up @@ -952,34 +966,44 @@ from shootblues import rpcSend
return fResult;
}

public static Future<byte[]> CallFunction (ProcessInfo process, string moduleName, string functionName, params object[] arguments) {
public static IFuture CallFunction (ProcessInfo process, string moduleName, string functionName, params object[] arguments) {
return CallFunction<object>(process, moduleName, functionName, arguments);
}

public static Future<T> CallFunction<T> (ProcessInfo process, string moduleName, string functionName, params object[] arguments) {
var f = new Future<T>();
var serializer = new JavaScriptSerializer();

if ((arguments != null) && (arguments.Length == 0))
arguments = null;

string argsJson = null;
if (arguments != null) {
var serializer = new JavaScriptSerializer();
if (arguments != null)
argsJson = serializer.Serialize(arguments);
}

return process.Channel.Send(new RPCMessage {
var inner = process.Channel.Send(new RPCMessage {
Type = RPCMessageType.CallFunction,
ModuleName = moduleName,
FunctionName = functionName,
Text = argsJson
}, true);
}

public static Future<T> CallFunction<T> (ProcessInfo process, string moduleName, string functionName, params object[] arguments) {
var f = new Future<T>();
var serializer = new JavaScriptSerializer();

var inner = CallFunction(process, moduleName, functionName, arguments);
inner.RegisterOnComplete((_) => {
if (!inner.Failed) {
try {
var json = inner.Result.DecodeUTF8Z();
f.Complete(serializer.Deserialize<T>(json));
try {
f.Complete(serializer.Deserialize<T>(json));
} catch (ArgumentException) {
string errorText;
if (arguments != null)
errorText = String.Format("Error when calling {0}.{1} with arguments {2}:\r\n{3}", moduleName, functionName, argsJson, json);
else
errorText = String.Format("Error when calling {0}.{1}:\r\n{2}", moduleName, functionName, json);
f.Fail(new PythonException(process, errorText));
}
} catch (Exception ex) {
f.Fail(ex);
}
Expand All @@ -1005,22 +1029,22 @@ private static IEnumerator<object> ReloadAllScripts (ScriptName[] scriptList) {
foreach (var pi in RunningProcesses) {
foreach (var scriptName in scriptList.Reverse()) {
if (pi.LoadedScripts.Contains(scriptName)) {
yield return LoadedScripts[scriptName].UnloadFrom(pi);
yield return new RunAsBackground(LoadedScripts[scriptName].UnloadFrom(pi));
pi.LoadedScripts.Remove(scriptName);
}
}
}

foreach (var scriptName in scriptList)
yield return LoadedScripts[scriptName].Reload();
yield return new RunAsBackground(LoadedScripts[scriptName].Reload());

foreach (var pi in RunningProcesses)
yield return LoadScriptsInto(pi, scriptList);
}

public static IEnumerator<object> LoadScriptsInto (ProcessInfo pi, ScriptName[] scriptList) {
foreach (var script in scriptList) {
yield return LoadedScripts[script].LoadInto(pi);
yield return new RunAsBackground(LoadedScripts[script].LoadInto(pi));
pi.LoadedScripts.Add(script);
}

Expand All @@ -1030,7 +1054,7 @@ public static IEnumerator<object> LoadScriptsInto (ProcessInfo pi, ScriptName[]
}));

foreach (var script in scriptList)
yield return LoadedScripts[script].LoadedInto(pi);
yield return new RunAsBackground(LoadedScripts[script].LoadedInto(pi));
}

private static IEnumerator<object> RPCTask (ProcessInfo pi) {
Expand Down
4 changes: 2 additions & 2 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.4.2.1")]
[assembly: AssemblyFileVersion("0.4.2.1")]
[assembly: AssemblyVersion("0.4.2.5")]
[assembly: AssemblyFileVersion("0.4.2.5")]
5 changes: 4 additions & 1 deletion payload/payload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,11 @@ void callFunction (const char * moduleName, const char * functionName, const cha
Py_XDECREF(loads);
Py_XDECREF(args);
Py_XDECREF(argsString);
if (!result)
if (!result) {
Py_XDECREF(module);
Py_XDECREF(function);
return errorHandler(messageId);
}
args = PySequence_Tuple(result);
Py_XDECREF(result);
}
Expand Down

0 comments on commit 69afd43

Please sign in to comment.