Re: segfault in method .pydate() of DateTime

"M.-A. Lemburg" <[email protected]> Fri, 27 Jan 2012 13:13:00 +0100
Newsgroups gmane.comp.python.egenix.user
Organization eGenix.com Software GmbH; http://www.egenix.com/
Message-ID <[email protected]>
M.-A. Lemburg wrote:
> Szoska, Daniel wrote:
>> Hello,
>>
>> Python dies with a segmentation fault, can someone reproduce this:
>>
>>>>> import mx.DateTime
>>>>> mx.DateTime.Date(2012, 1, 1).pydate()
>> segmentation fault
>>
>> This happens with .pydatetime() and .pytime() too.
>>
>> I tried it with Python 2.7.2, egenix-mx-base 3.2.2 under Linux, Max OS 10.7
>> and Windows XP.
> 
> Thank you for reporting this.
> 
> We have done some preliminary tests and it appears to be caused
> by the fact that mxDateTime uses a lazy import of the datetime
> module to implement interfacing with Python's datetime module
> types.
> 
> The problem doesn't show up in the tests because the datetime
> module's C API is already initialized by the time the .pydate()
> (et al.) tests are run.
> 
> We will issue a new patch level release to address the problem.
> 
> Until then, please use the following trick to force initialization
> of the datetime C API in mxDateTime:
> 
> # Trick to force initialization of the datetime C API in mxDateTime:
> import mx.DateTime
> import datetime
> mx.DateTime.today() == datetime.date.today()
> 
> Background: The comparison causes a forced initialization.

Here's a patch which fixes the problem.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Source  (#1, Jan 27 2012)
>>> Python/Zope Consulting and Support ...        http://www.egenix.com/
>>> mxODBC.Zope.Database.Adapter ...             http://zope.egenix.com/
>>> mxODBC, mxDateTime, mxTextTools ...        http://python.egenix.com/
________________________________________________________________________

::: Try our new mxODBC.Connect Python Database Interface for free ! ::::


   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
           Registered at Amtsgericht Duesseldorf: HRB 46611
               http://www.egenix.com/company/contact/


_______________________________________________________________________
eGenix.com User Mailing List                     http://www.egenix.com/
https://www.egenix.com/mailman/listinfo/egenix-users
changeset_25267.diff (text/x-patch, 4.9 KB)
Index: /trunk/egenix/projects/mx/DateTime/mxDateTime/mxDateTime.c
===================================================================
--- /trunk/egenix/projects/mx/DateTime/mxDateTime/mxDateTime.c	(revision 25256)
+++ /trunk/egenix/projects/mx/DateTime/mxDateTime/mxDateTime.c	(revision 25267)
@@ -2618,5 +2618,9 @@
 	      "DateTime object values out of range for "
 	      "dateime.date objects");
-    
+
+    /* Make sure the PyDateTimeAPI is loaded */
+    if (mx_Require_PyDateTimeAPI())
+	goto onError;
+
     /* Build new object */
     return PyDate_FromDate((int)datetime->year,
@@ -2645,4 +2649,8 @@
     microsecond = (int)((datetime->second - (double)second) * 1e6);
     
+    /* Make sure the PyDateTimeAPI is loaded */
+    if (mx_Require_PyDateTimeAPI())
+	goto onError;
+
     /* Build new object */
     return PyDateTime_FromDateAndTime((int)datetime->year,
@@ -2671,4 +2679,8 @@
     microsecond = (int)((datetime->second - (double)second) * 1e6);
     
+    /* Make sure the PyDateTimeAPI is loaded */
+    if (mx_Require_PyDateTimeAPI())
+	goto onError;
+
     /* Build new object */
     return PyTime_FromTime((int)datetime->hour,
@@ -4638,7 +4650,12 @@
     else if (mx_PyDelta_Check(right)) {
 	/* DateTimeDelta op PyDelta */
-	double t1 = mx_PyDeltaInSeconds(right);
-	double t0 = mxDateTimeDelta_AsDouble(self);
-
+	double t0, t1;
+
+	/* Make sure the PyDateTimeAPI is loaded */
+	if (mx_Require_PyDateTimeAPI())
+	    goto onError;
+
+	t0 = mxDateTimeDelta_AsDouble(self);
+	t1 = mx_PyDeltaInSeconds(right);
 	if ((t0 == -1.0 || t1 == -1.0) && PyErr_Occurred())
 	    goto onError;
@@ -4648,7 +4665,12 @@
     else if (mx_PyTime_Check(right)) {
 	/* DateTimeDelta op PyTime */
-	double t1 = mx_PyTimeInSeconds(right);
-	double t0 = mxDateTimeDelta_AsDouble(self);
-
+	double t0, t1;
+
+	/* Make sure the PyDateTimeAPI is loaded */
+	if (mx_Require_PyDateTimeAPI())
+	    goto onError;
+
+	t0 = mxDateTimeDelta_AsDouble(self);
+	t1 = mx_PyTimeInSeconds(right);
 	if ((t0 == -1.0 || t1 == -1.0) && PyErr_Occurred())
 	    goto onError;
@@ -4774,7 +4796,14 @@
 	    /* DateTimeDelta + PyDelta */
 	    value = mx_PyDeltaInSeconds(right);
-	else if (mx_PyTime_Check(right))
+
+	else if (mx_PyTime_Check(right)) {
+
+    	    /* Make sure the PyDateTimeAPI is loaded */
+	    if (mx_Require_PyDateTimeAPI())
+		goto onError;
+
 	    /* DateTimeDelta + PyTime */
 	    value = mx_PyTimeInSeconds(right);
+	}
 #endif
 	else {
@@ -4840,7 +4869,14 @@
 		/* DateTimeDelta - PyDelta */
 		value = mx_PyDeltaInSeconds(right);
-	    else if (mx_PyTime_Check(right))
+
+	    else if (mx_PyTime_Check(right)) {
+		
+		/* Make sure the PyDateTimeAPI is loaded */
+		if (mx_Require_PyDateTimeAPI())
+		    goto onError;
+
 		/* DateTimeDelta - PyTime */
 		value = mx_PyTimeInSeconds(right);
+	    }
 #endif
 	    else {
@@ -4881,7 +4917,14 @@
 		/* PyDelta - DateTimeDelta */
 		value = mx_PyDeltaInSeconds(left);
-	    else if (mx_PyTime_Check(left))
+
+	    else if (mx_PyTime_Check(left)) {
+
+		/* Make sure the PyDateTimeAPI is loaded */
+		if (mx_Require_PyDateTimeAPI())
+		    goto onError;
+
 		/* PyTime - DateTimeDelta */
 		value = mx_PyTimeInSeconds(left);
+	    }
 #endif
 	    else {
@@ -4998,7 +5041,14 @@
 	    /* DateTimeDelta / PyDelta */
 	    value = mx_PyDeltaInSeconds(right);
-	else if (mx_PyTime_Check(right))
+
+	else if (mx_PyTime_Check(right)) {
+	    
+	    /* Make sure the PyDateTimeAPI is loaded */
+	    if (mx_Require_PyDateTimeAPI())
+		goto onError;
+
 	    /* DateTimeDelta / PyTime */
 	    value = mx_PyTimeInSeconds(right);
+	}
 #endif
 	else if (PyFloat_Compatible(right)) {
@@ -5045,7 +5095,14 @@
 	    /* PyDelta / DateTimeDelta */
 	    value = mx_PyDeltaInSeconds(left);
-	else if (mx_PyTime_Check(left))
+
+	else if (mx_PyTime_Check(left)) {
+	    
+	    /* Make sure the PyDateTimeAPI is loaded */
+	    if (mx_Require_PyDateTimeAPI())
+		goto onError;
+	
 	    /* PyTime / DateTimeDelta */
 	    value = mx_PyTimeInSeconds(left);
+	}
 #endif
 	else if (PyFloat_Compatible(left)) {
Index: /trunk/egenix/projects/mx/DateTime/mxDateTime/testpydatetime.py
===================================================================
--- /trunk/egenix/projects/mx/DateTime/mxDateTime/testpydatetime.py	(revision 25070)
+++ /trunk/egenix/projects/mx/DateTime/mxDateTime/testpydatetime.py	(revision 25267)
@@ -24,4 +24,11 @@
     mxdtd2 = DateTimeDelta(0, 11, 30, 13)
 
+    # Constructor methods
+    assert mxdt1.pydate() == pyd1
+    assert mxdt1.pydatetime() == pydt1
+    assert mxdt1.pytime() == pyt1
+    assert mxdtd1.pytime() == pyt1
+    assert mxdtd1.pytimedelta() == pytd1
+    
     # Comparisons
     assert pydt1 == mxdt1
@@ -56,9 +63,2 @@
     assert mxdtd2 == TimeDeltaFrom(pyt2), (mxdtd2, TimeDeltaFrom(pyt2))
 
-    # Constructor methods
-    assert mxdt1.pydate() == pyd1
-    assert mxdt1.pydatetime() == pydt1
-    assert mxdt1.pytime() == pyt1
-    assert mxdtd1.pytime() == pyt1
-    assert mxdtd1.pytimedelta() == pytd1
-