Skip to content

Commit a50b3a4

Browse files
keep the old UNWRAP Macro and create a new MACRO UNWRAP_OR to cleam the
resources if old unwrap fails
1 parent b4e0de8 commit a50b3a4

File tree

1 file changed

+56
-76
lines changed

1 file changed

+56
-76
lines changed

Objects/weakrefobject.c

Lines changed: 56 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -530,39 +530,42 @@ proxy_check_ref(PyObject *obj)
530530
return true;
531531
}
532532

533-
/*
534-
* Unwrap a proxy into a strong reference.
535-
* - If `o` is a live proxy: replaces `o` with the underlying object
536-
* (already Py_INCREF'd by _PyWeakref_GET_REF), sets *did_incref = 1.
537-
* - If `o` is a dead proxy: sets ReferenceError, sets `o` = NULL,
538-
* sets *did_incref = 0.
539-
* - If `o` is not a proxy: Py_INCREF's it, sets *did_incref = 1.
540-
* Returns 1 on success, 0 on dead proxy (caller must goto error).
533+
534+
/* If a parameter is a proxy, check that it is still "live" and wrap it,
535+
* replacing the original value with the raw object. Raises ReferenceError
536+
* if the param is a dead proxy.
541537
*/
542-
static inline int
543-
_proxy_unwrap(PyObject **op, int *did_incref)
544-
{
545-
if (PyWeakref_CheckProxy(*op)) {
546-
*op = _PyWeakref_GET_REF(*op);
547-
if (!proxy_check_ref(*op)) {
548-
*did_incref = 0;
549-
return 0;
538+
#define UNWRAP(o) \
539+
if (PyWeakref_CheckProxy(o)) { \
540+
o = _PyWeakref_GET_REF(o); \
541+
if (!proxy_check_ref(o)) { \
542+
return NULL; \
543+
} \
544+
} \
545+
else { \
546+
Py_INCREF(o); \
547+
}
548+
549+
/* Like UNWRAP, but executes `cleanup` before returning NULL.
550+
* Use when a prior UNWRAP has already incremented a refcount that
551+
* must be released if this unwrap fails.
552+
*/
553+
#define UNWRAP_OR(o, cleanup) \
554+
if (PyWeakref_CheckProxy(o)) { \
555+
o = _PyWeakref_GET_REF(o); \
556+
if (!proxy_check_ref(o)) { \
557+
cleanup; \
558+
return NULL; \
559+
} \
560+
} \
561+
else { \
562+
Py_INCREF(o); \
550563
}
551-
/* _PyWeakref_GET_REF already returned a strong ref */
552-
}
553-
else {
554-
Py_INCREF(*op);
555-
}
556-
*did_incref = 1;
557-
return 1;
558-
}
559564

560565
#define WRAP_UNARY(method, generic) \
561566
static PyObject * \
562567
method(PyObject *proxy) { \
563-
int proxy_incref = 0; \
564-
if (!_proxy_unwrap(&proxy, &proxy_incref)) \
565-
return NULL; \
568+
UNWRAP(proxy); \
566569
PyObject* res = generic(proxy); \
567570
Py_DECREF(proxy); \
568571
return res; \
@@ -571,19 +574,12 @@ _proxy_unwrap(PyObject **op, int *did_incref)
571574
#define WRAP_BINARY(method, generic) \
572575
static PyObject * \
573576
method(PyObject *x, PyObject *y) { \
574-
int x_incref = 0, y_incref = 0; \
575-
if (!_proxy_unwrap(&x, &x_incref)) goto clean_up; \
576-
if (!_proxy_unwrap(&y, &y_incref)) goto clean_up; \
577-
{ \
578-
PyObject* res = generic(x, y); \
579-
Py_DECREF(x); \
580-
Py_DECREF(y); \
581-
return res; \
582-
} \
583-
clean_up: \
584-
if (x_incref) Py_DECREF(x); \
585-
if (y_incref) Py_DECREF(y); \
586-
return NULL; \
577+
UNWRAP(x); \
578+
UNWRAP_OR(y, Py_DECREF(x)); \
579+
PyObject* res = generic(x, y); \
580+
Py_DECREF(x); \
581+
Py_DECREF(y); \
582+
return res; \
587583
}
588584

589585
/* Note that the third arg needs to be checked for NULL since the tp_call
@@ -592,36 +588,27 @@ _proxy_unwrap(PyObject **op, int *did_incref)
592588
#define WRAP_TERNARY(method, generic) \
593589
static PyObject * \
594590
method(PyObject *proxy, PyObject *v, PyObject *w) { \
595-
int proxy_incref = 0, v_incref = 0, w_incref = 0; \
596-
if (!_proxy_unwrap(&proxy, &proxy_incref)) goto clean_up; \
597-
if (!_proxy_unwrap(&v, &v_incref)) goto clean_up; \
591+
UNWRAP(proxy); \
592+
UNWRAP_OR(v, Py_DECREF(proxy)); \
598593
if (w != NULL) { \
599-
if (!_proxy_unwrap(&w, &w_incref)) goto clean_up; \
594+
UNWRAP_OR(w, Py_DECREF(proxy); Py_DECREF(v)); \
600595
} \
601-
{ \
602-
PyObject* res = generic(proxy, v, w); \
603-
Py_DECREF(proxy); \
604-
Py_DECREF(v); \
605-
Py_XDECREF(w); \
606-
return res; \
607-
} \
608-
clean_up: \
609-
if (proxy_incref) Py_DECREF(proxy); \
610-
if (v_incref) Py_DECREF(v); \
611-
if (w_incref) Py_DECREF(w); \
612-
return NULL; \
596+
PyObject* res = generic(proxy, v, w); \
597+
Py_DECREF(proxy); \
598+
Py_DECREF(v); \
599+
Py_XDECREF(w); \
600+
return res; \
613601
}
614602

615603
#define WRAP_METHOD(method, SPECIAL) \
616604
static PyObject * \
617605
method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
618-
int proxy_incref = 0; \
619-
if (!_proxy_unwrap(&proxy, &proxy_incref)) \
620-
return NULL; \
621-
PyObject* res = PyObject_CallMethodNoArgs(proxy, &_Py_ID(SPECIAL)); \
622-
Py_DECREF(proxy); \
623-
return res; \
624-
}
606+
UNWRAP(proxy); \
607+
PyObject* res = PyObject_CallMethodNoArgs(proxy, &_Py_ID(SPECIAL)); \
608+
Py_DECREF(proxy); \
609+
return res; \
610+
}
611+
625612

626613
/* direct slots */
627614

@@ -664,19 +651,12 @@ proxy_setattr(PyObject *proxy, PyObject *name, PyObject *value)
664651
static PyObject *
665652
proxy_richcompare(PyObject *proxy, PyObject *v, int op)
666653
{
667-
int proxy_incref = 0, v_incref = 0;
668-
if (!_proxy_unwrap(&proxy, &proxy_incref)) goto clean_up;
669-
if (!_proxy_unwrap(&v, &v_incref)) goto clean_up;
670-
{
671-
PyObject* res = PyObject_RichCompare(proxy, v, op);
672-
Py_DECREF(proxy);
673-
Py_DECREF(v);
674-
return res;
675-
}
676-
clean_up:
677-
if (proxy_incref) Py_DECREF(proxy);
678-
if (v_incref) Py_DECREF(v);
679-
return NULL;
654+
UNWRAP(proxy);
655+
UNWRAP_OR(v, Py_DECREF(proxy));
656+
PyObject* res = PyObject_RichCompare(proxy, v, op);
657+
Py_DECREF(proxy);
658+
Py_DECREF(v);
659+
return res;
680660
}
681661

682662
/* number slots */

0 commit comments

Comments
 (0)