Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
f3bb2839
Kaydet (Commit)
f3bb2839
authored
Nis 25, 2008
tarafından
Thomas Heller
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #2682: ctypes callback functions no longer contain a cyclic
reference to themselves. Backport from trunk.
üst
8d904c39
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
138 additions
and
51 deletions
+138
-51
NEWS
Misc/NEWS
+3
-0
_ctypes.c
Modules/_ctypes/_ctypes.c
+13
-25
callbacks.c
Modules/_ctypes/callbacks.c
+111
-19
ctypes.h
Modules/_ctypes/ctypes.h
+11
-7
No files found.
Misc/NEWS
Dosyayı görüntüle @
f3bb2839
...
...
@@ -45,6 +45,9 @@ Core and builtins
Library
-------
-
Issue
#
2682
:
ctypes
callback
functions
no
longer
contain
a
cyclic
reference
to
themselves
.
-
Issue
#
2670
:
Fix
a
failure
in
urllib2
.
build_opener
(),
when
passed
two
handlers
that
derive
the
same
default
base
class
.
...
...
Modules/_ctypes/_ctypes.c
Dosyayı görüntüle @
f3bb2839
...
...
@@ -2878,7 +2878,7 @@ CFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
CFuncPtrObject
*
self
;
PyObject
*
callable
;
StgDictObject
*
dict
;
ffi_info
*
thunk
;
CThunkObject
*
thunk
;
if
(
PyTuple_GET_SIZE
(
args
)
==
0
)
return
GenericCData_new
(
type
,
args
,
kwds
);
...
...
@@ -2935,11 +2935,6 @@ CFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return
NULL
;
}
/*****************************************************************/
/* The thunk keeps unowned references to callable and dict->argtypes
so we have to keep them alive somewhere else: callable is kept in self,
dict->argtypes is in the type's stgdict.
*/
thunk
=
AllocFunctionCallback
(
callable
,
dict
->
argtypes
,
dict
->
restype
,
...
...
@@ -2948,27 +2943,22 @@ CFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return
NULL
;
self
=
(
CFuncPtrObject
*
)
GenericCData_new
(
type
,
args
,
kwds
);
if
(
self
==
NULL
)
if
(
self
==
NULL
)
{
Py_DECREF
(
thunk
);
return
NULL
;
}
Py_INCREF
(
callable
);
self
->
callable
=
callable
;
self
->
thunk
=
thunk
;
*
(
void
**
)
self
->
b_ptr
=
*
(
void
**
)
thunk
;
/* We store ourself in self->b_objects[0], because the whole instance
must be kept alive if stored in a structure field, for example.
Cycle GC to the rescue! And we have a unittest proving that this works
correctly...
*/
Py_INCREF
((
PyObject
*
)
self
);
/* for KeepRef */
if
(
-
1
==
KeepRef
((
CDataObject
*
)
self
,
0
,
(
PyObject
*
)
self
))
{
*
(
void
**
)
self
->
b_ptr
=
(
void
*
)
thunk
->
pcl
;
Py_INCREF
((
PyObject
*
)
thunk
);
/* for KeepRef */
if
(
-
1
==
KeepRef
((
CDataObject
*
)
self
,
0
,
(
PyObject
*
)
thunk
))
{
Py_DECREF
((
PyObject
*
)
self
);
return
NULL
;
}
return
(
PyObject
*
)
self
;
}
...
...
@@ -3415,6 +3405,7 @@ CFuncPtr_traverse(CFuncPtrObject *self, visitproc visit, void *arg)
Py_VISIT
(
self
->
argtypes
);
Py_VISIT
(
self
->
converters
);
Py_VISIT
(
self
->
paramflags
);
Py_VISIT
(
self
->
thunk
);
return
CData_traverse
((
CDataObject
*
)
self
,
visit
,
arg
);
}
...
...
@@ -3428,13 +3419,7 @@ CFuncPtr_clear(CFuncPtrObject *self)
Py_CLEAR
(
self
->
argtypes
);
Py_CLEAR
(
self
->
converters
);
Py_CLEAR
(
self
->
paramflags
);
if
(
self
->
thunk
)
{
FreeClosure
(
self
->
thunk
->
pcl
);
PyMem_Free
(
self
->
thunk
);
self
->
thunk
=
NULL
;
}
Py_CLEAR
(
self
->
thunk
);
return
CData_clear
((
CDataObject
*
)
self
);
}
...
...
@@ -4673,6 +4658,9 @@ init_ctypes(void)
if
(
PyType_Ready
(
&
PyCArg_Type
)
<
0
)
return
;
if
(
PyType_Ready
(
&
CThunk_Type
)
<
0
)
return
;
/* StgDict is derived from PyDict_Type */
StgDict_Type
.
tp_base
=
&
PyDict_Type
;
if
(
PyType_Ready
(
&
StgDict_Type
)
<
0
)
...
...
Modules/_ctypes/callbacks.c
Dosyayı görüntüle @
f3bb2839
...
...
@@ -12,6 +12,74 @@
#endif
#include "ctypes.h"
/**************************************************************/
static
CThunkObject_dealloc
(
PyObject
*
_self
)
{
CThunkObject
*
self
=
(
CThunkObject
*
)
_self
;
Py_XDECREF
(
self
->
converters
);
Py_XDECREF
(
self
->
callable
);
Py_XDECREF
(
self
->
restype
);
if
(
self
->
pcl
)
FreeClosure
(
self
->
pcl
);
PyObject_Del
(
self
);
}
static
int
CThunkObject_traverse
(
PyObject
*
_self
,
visitproc
visit
,
void
*
arg
)
{
CThunkObject
*
self
=
(
CThunkObject
*
)
_self
;
Py_VISIT
(
self
->
converters
);
Py_VISIT
(
self
->
callable
);
Py_VISIT
(
self
->
restype
);
return
0
;
}
static
int
CThunkObject_clear
(
PyObject
*
_self
)
{
CThunkObject
*
self
=
(
CThunkObject
*
)
_self
;
Py_CLEAR
(
self
->
converters
);
Py_CLEAR
(
self
->
callable
);
Py_CLEAR
(
self
->
restype
);
return
0
;
}
PyTypeObject
CThunk_Type
=
{
PyObject_HEAD_INIT
(
NULL
)
0
,
"_ctypes.CThunkObject"
,
sizeof
(
CThunkObject
),
/* tp_basicsize */
sizeof
(
ffi_type
),
/* tp_itemsize */
CThunkObject_dealloc
,
/* tp_dealloc */
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_compare */
0
,
/* tp_repr */
0
,
/* tp_as_number */
0
,
/* tp_as_sequence */
0
,
/* tp_as_mapping */
0
,
/* tp_hash */
0
,
/* tp_call */
0
,
/* tp_str */
0
,
/* tp_getattro */
0
,
/* tp_setattro */
0
,
/* tp_as_buffer */
Py_TPFLAGS_DEFAULT
,
/* tp_flags */
"CThunkObject"
,
/* tp_doc */
CThunkObject_traverse
,
/* tp_traverse */
CThunkObject_clear
,
/* tp_clear */
0
,
/* tp_richcompare */
0
,
/* tp_weaklistoffset */
0
,
/* tp_iter */
0
,
/* tp_iternext */
0
,
/* tp_methods */
0
,
/* tp_members */
};
/**************************************************************/
static
void
PrintError
(
char
*
msg
,
...)
{
...
...
@@ -247,32 +315,56 @@ static void closure_fcn(ffi_cif *cif,
void
**
args
,
void
*
userdata
)
{
ffi_info
*
p
=
userdata
;
CThunkObject
*
p
=
(
CThunkObject
*
)
userdata
;
_CallPythonObject
(
resp
,
p
->
restype
,
p
->
ffi_
restype
,
p
->
setfunc
,
p
->
callable
,
p
->
converters
,
args
);
}
ffi_info
*
AllocFunctionCallback
(
PyObject
*
callable
,
PyObject
*
converters
,
PyObject
*
restype
,
int
is_cdecl
)
static
CThunkObject
*
CThunkObject_new
(
Py_ssize_t
nArgs
)
{
CThunkObject
*
p
;
int
i
;
p
=
PyObject_NewVar
(
CThunkObject
,
&
CThunk_Type
,
nArgs
);
if
(
p
==
NULL
)
{
PyErr_NoMemory
();
return
NULL
;
}
p
->
pcl
=
NULL
;
memset
(
&
p
->
cif
,
0
,
sizeof
(
p
->
cif
));
p
->
converters
=
NULL
;
p
->
callable
=
NULL
;
p
->
setfunc
=
NULL
;
p
->
ffi_restype
=
NULL
;
for
(
i
=
0
;
i
<
nArgs
+
1
;
++
i
)
p
->
atypes
[
i
]
=
NULL
;
return
p
;
}
CThunkObject
*
AllocFunctionCallback
(
PyObject
*
callable
,
PyObject
*
converters
,
PyObject
*
restype
,
int
is_cdecl
)
{
int
result
;
ffi_info
*
p
;
CThunkObject
*
p
;
int
nArgs
,
i
;
ffi_abi
cc
;
nArgs
=
PySequence_Size
(
converters
);
p
=
(
ffi_info
*
)
PyMem_Malloc
(
sizeof
(
ffi_info
)
+
sizeof
(
ffi_type
)
*
(
nArgs
));
if
(
p
==
NULL
)
{
PyErr_NoMemory
();
p
=
CThunkObject_new
(
nArgs
);
if
(
p
==
NULL
)
return
NULL
;
}
assert
(
CThunk_CheckExact
(
p
));
p
->
pcl
=
MallocClosure
();
if
(
p
->
pcl
==
NULL
)
{
PyErr_NoMemory
();
...
...
@@ -288,9 +380,11 @@ ffi_info *AllocFunctionCallback(PyObject *callable,
}
p
->
atypes
[
i
]
=
NULL
;
Py_INCREF
(
restype
);
p
->
restype
=
restype
;
if
(
restype
==
Py_None
)
{
p
->
setfunc
=
NULL
;
p
->
restype
=
&
ffi_type_void
;
p
->
ffi_
restype
=
&
ffi_type_void
;
}
else
{
StgDictObject
*
dict
=
PyType_stgdict
(
restype
);
if
(
dict
==
NULL
||
dict
->
setfunc
==
NULL
)
{
...
...
@@ -299,7 +393,7 @@ ffi_info *AllocFunctionCallback(PyObject *callable,
goto
error
;
}
p
->
setfunc
=
dict
->
setfunc
;
p
->
restype
=
&
dict
->
ffi_type_pointer
;
p
->
ffi_
restype
=
&
dict
->
ffi_type_pointer
;
}
cc
=
FFI_DEFAULT_ABI
;
...
...
@@ -322,16 +416,14 @@ ffi_info *AllocFunctionCallback(PyObject *callable,
goto
error
;
}
Py_INCREF
(
converters
);
p
->
converters
=
converters
;
Py_INCREF
(
callable
);
p
->
callable
=
callable
;
return
p
;
error:
if
(
p
)
{
if
(
p
->
pcl
)
FreeClosure
(
p
->
pcl
);
PyMem_Free
(
p
);
}
Py_XDECREF
(
p
);
return
NULL
;
}
...
...
Modules/_ctypes/ctypes.h
Dosyayı görüntüle @
f3bb2839
...
...
@@ -68,14 +68,18 @@ struct tagCDataObject {
};
typedef
struct
{
PyObject_VAR_HEAD
ffi_closure
*
pcl
;
/* the C callable */
ffi_cif
cif
;
PyObject
*
converters
;
PyObject
*
callable
;
PyObject
*
restype
;
SETFUNC
setfunc
;
ffi_type
*
restype
;
ffi_type
*
ffi_
restype
;
ffi_type
*
atypes
[
1
];
}
ffi_info
;
}
CThunkObject
;
extern
PyTypeObject
CThunk_Type
;
#define CThunk_CheckExact(v) ((v)->ob_type == &CThunk_Type)
typedef
struct
{
/* First part identical to tagCDataObject */
...
...
@@ -91,7 +95,7 @@ typedef struct {
union
value
b_value
;
/* end of tagCDataObject, additional fields follow */
ffi_info
*
thunk
;
CThunkObject
*
thunk
;
PyObject
*
callable
;
/* These two fields will override the ones in the type's stgdict if
...
...
@@ -162,10 +166,10 @@ extern void init_callbacks_in_module(PyObject *m);
extern
PyMethodDef
module_methods
[];
extern
ffi_info
*
AllocFunctionCallback
(
PyObject
*
callable
,
PyObject
*
converters
,
PyObject
*
restype
,
int
stdcall
);
extern
CThunkObject
*
AllocFunctionCallback
(
PyObject
*
callable
,
PyObject
*
converters
,
PyObject
*
restype
,
int
stdcall
);
/* a table entry describing a predefined ctypes type */
struct
fielddesc
{
char
code
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment