[Python.NET] [PythonNet] 8/ 4 Resolve "Reentrancy bug"

Collector: Python for .NET Issue ... pythondotnet at python.org
Thu Mar 31 20:21:15 CEST 2005


Issue #8 Update (Resolve) "Reentrancy bug"
 Status Resolved, General/bug medium
To followup, visit:
  http://www.zope.org/Members/Brian/PythonNet/Collector/8

==============================================================
= Resolve - Entry #4 by Brian on Mar 31, 2005 1:21 pm

 Status: Pending => Resolved

Great - thanks for the followup.

I'm going to work on a 'tutorial for 
embedders' for the next release, as this 
isn't nearly well-documented enough...

-BL
________________________________________
= Comment - Entry #3 by Anonymous User on Mar 31, 2005 12:59 pm

You're right -- the bug is indeed caused by the lack of a lock acquisition in that code.  Thanks for the tip.  This item should be closed.

> = Comment - Entry #2 by Brian on Mar 31, 2005 9:45 am
> 
> Note that to be thread-safe and reentrancy-safe you 
> also need to make sure that any managed code you have 
> that uses Python.Runtime objects or methods is acquiring 
> the Python lock first. For example:
> 
> public class Example {
> 
>   public static int MethodThatCallsPython() {
>     // have to acquire the GIL to safely call back into
>     // Python!!
>     IntPtr state = PythonEngine.AcquireLock();
> 
>     PythonEngine.RunSimpleString("print 'hello'");
> 
>     // done using python for now, so release the GIL...
>     PythonEngine.ReleaseLock(state);
>   }
> 
> }
> 
> Forgetting to manage the lock around a callback into Python 
> is almost certain to cause a NullReferenceException (because 
> there will be no valid thread state when the callback is 
> made).
> 
> ________________________________________
> = Request - Entry #1 by Anonymous User on Mar 30, 2005 8:10 pm
> 
> There is a reentrancy problem when calling CLR code from Python that
>   calls back into Python.  The sequence I use to reproduce the problem is
>   fairly simple:
> 1) Execute some Python code either through PyObject.InvokeMethod, or 
> PythonEngine.RunSimpleString.
> 2) From the executed Python code, call into a CLR class.
> 3) From the CLR class, execute Python code again.
> 
> Here is some example code that demonstrates the issue:
> using System;
> using Python.Runtime;
> 
> namespace PDNBug {
> 	public class Example {
> 		[STAThread]
> 		static void Main(string[] args) {
> 			PythonEngine.Initialize();
> 			PythonEngine.RunSimpleString("from CLR.PDNBug import
>   			Example\nExample.FirstCall()");
> 		}
> 
> 		public static void FirstCall () {
> 			Console.WriteLine("First call succeeded.");
> 			PythonEngine.RunSimpleString("from CLR.PDNBug import
>   			Example\nExample.SecondCall()");
> 		}
> 
> 		public static void SecondCall () {
> 			Console.WriteLine("Second call succeeded.");
> 		}
> 	}
> }
> 
> The output generated is:
> First call succeeded.
> Traceback (most recent call last):
>   File "<string>", line 2, in ?
> System.NullReferenceException: Object reference not set to an instance of
>   an object.
>    at Python.Runtime.Runtime.PyRun_SimpleString(String code)
>    at Python.Runtime.PythonEngine.RunSimpleString(String code)
>    at PDNBug.Example.FirstCall() in example.cs:line 15: Object reference
>      not set to an instance of an object.
> 
> The expected output is:
> First call succeeded.
> Second call succeeded.
> 
> This issue was previously posted to the mailing list
>   (http://mail.python.org/pipermail/pythondotnet/2005-January/000235.html).
________________________________________
= Comment - Entry #2 by Brian on Mar 31, 2005 9:45 am

Note that to be thread-safe and reentrancy-safe you 
also need to make sure that any managed code you have 
that uses Python.Runtime objects or methods is acquiring 
the Python lock first. For example:

public class Example {

  public static int MethodThatCallsPython() {
    // have to acquire the GIL to safely call back into
    // Python!!
    IntPtr state = PythonEngine.AcquireLock();

    PythonEngine.RunSimpleString("print 'hello'");

    // done using python for now, so release the GIL...
    PythonEngine.ReleaseLock(state);
  }

}

Forgetting to manage the lock around a callback into Python 
is almost certain to cause a NullReferenceException (because 
there will be no valid thread state when the callback is 
made).

________________________________________
= Request - Entry #1 by Anonymous User on Mar 30, 2005 8:10 pm

There is a reentrancy problem when calling CLR code from Python that calls back into Python.  The sequence I use to reproduce the problem is fairly simple:
1) Execute some Python code either through PyObject.InvokeMethod, or 
PythonEngine.RunSimpleString.
2) From the executed Python code, call into a CLR class.
3) From the CLR class, execute Python code again.

Here is some example code that demonstrates the issue:
using System;
using Python.Runtime;

namespace PDNBug {
	public class Example {
		[STAThread]
		static void Main(string[] args) {
			PythonEngine.Initialize();
			PythonEngine.RunSimpleString("from CLR.PDNBug import Example\nExample.FirstCall()");
		}

		public static void FirstCall () {
			Console.WriteLine("First call succeeded.");
			PythonEngine.RunSimpleString("from CLR.PDNBug import Example\nExample.SecondCall()");
		}

		public static void SecondCall () {
			Console.WriteLine("Second call succeeded.");
		}
	}
}

The output generated is:
First call succeeded.
Traceback (most recent call last):
  File "<string>", line 2, in ?
System.NullReferenceException: Object reference not set to an instance of an object.
   at Python.Runtime.Runtime.PyRun_SimpleString(String code)
   at Python.Runtime.PythonEngine.RunSimpleString(String code)
   at PDNBug.Example.FirstCall() in example.cs:line 15: Object reference not set to an instance of an object.

The expected output is:
First call succeeded.
Second call succeeded.

This issue was previously posted to the mailing list (http://mail.python.org/pipermail/pythondotnet/2005-January/000235.html).
==============================================================



More information about the PythonDotNet mailing list