@@ -62,9 +62,12 @@ typedef struct {
62
62
char * str ; /* Human readable representation of error, if one
63
63
* was provided by librdkafka.
64
64
* Else falls back on err2str(). */
65
+ int fatal ; /**< Set to true if a fatal error. */
65
66
} KafkaError ;
66
67
67
68
69
+ static void cfl_PyErr_Fatal (rd_kafka_resp_err_t err , const char * reason );
70
+
68
71
static PyObject * KafkaError_code (KafkaError * self , PyObject * ignore ) {
69
72
return cfl_PyInt_FromInt (self -> code );
70
73
}
@@ -81,6 +84,20 @@ static PyObject *KafkaError_name (KafkaError *self, PyObject *ignore) {
81
84
return cfl_PyUnistr (_FromString (rd_kafka_err2name (self -> code )));
82
85
}
83
86
87
+ static PyObject * KafkaError_fatal (KafkaError * self , PyObject * ignore ) {
88
+ PyObject * ret = self -> fatal ? Py_True : Py_False ;
89
+ Py_INCREF (ret );
90
+ return ret ;
91
+ }
92
+
93
+
94
+ static PyObject * KafkaError_test_raise_fatal (KafkaError * null ,
95
+ PyObject * ignore ) {
96
+ cfl_PyErr_Fatal (RD_KAFKA_RESP_ERR__INVALID_ARG ,
97
+ "This is a fatal exception for testing purposes" );
98
+ return NULL ;
99
+ }
100
+
84
101
85
102
static PyMethodDef KafkaError_methods [] = {
86
103
{ "code" , (PyCFunction )KafkaError_code , METH_NOARGS ,
@@ -105,6 +122,14 @@ static PyMethodDef KafkaError_methods[] = {
105
122
" :rtype: str\n"
106
123
"\n"
107
124
},
125
+ { "fatal" , (PyCFunction )KafkaError_fatal , METH_NOARGS ,
126
+ " :returns: True if this a fatal error, else False.\n"
127
+ " :rtype: bool\n"
128
+ "\n"
129
+ },
130
+ { "_test_raise_fatal" , (PyCFunction )KafkaError_test_raise_fatal ,
131
+ METH_NOARGS |METH_STATIC
132
+ },
108
133
109
134
{ NULL }
110
135
};
@@ -133,7 +158,8 @@ static int KafkaError_traverse (KafkaError *self,
133
158
}
134
159
135
160
static PyObject * KafkaError_str0 (KafkaError * self ) {
136
- return cfl_PyUnistr (_FromFormat ("KafkaError{code=%s,val=%d,str=\"%s\"}" ,
161
+ return cfl_PyUnistr (_FromFormat ("KafkaError{%scode=%s,val=%d,str=\"%s\"}" ,
162
+ self -> fatal ?"FATAL," :"" ,
137
163
rd_kafka_err2name (self -> code ),
138
164
self -> code ,
139
165
self -> str ? self -> str :
@@ -247,6 +273,7 @@ static PyTypeObject KafkaErrorType = {
247
273
static void KafkaError_init (KafkaError * self ,
248
274
rd_kafka_resp_err_t code , const char * str ) {
249
275
self -> code = code ;
276
+ self -> fatal = 0 ;
250
277
if (str )
251
278
self -> str = strdup (str );
252
279
else
@@ -292,6 +319,17 @@ PyObject *KafkaError_new0 (rd_kafka_resp_err_t err, const char *fmt, ...) {
292
319
}
293
320
294
321
322
+ /**
323
+ * @brief Raise exception from fatal error.
324
+ */
325
+ static void cfl_PyErr_Fatal (rd_kafka_resp_err_t err , const char * reason ) {
326
+ PyObject * eo = KafkaError_new0 (err , "%s" , reason );
327
+ ((KafkaError * )eo )-> fatal = 1 ;
328
+ PyErr_SetObject (KafkaException , eo );
329
+ }
330
+
331
+
332
+
295
333
296
334
297
335
/****************************************************************************
@@ -1162,6 +1200,7 @@ PyObject *c_headers_to_py (rd_kafka_headers_t *headers) {
1162
1200
}
1163
1201
#endif
1164
1202
1203
+
1165
1204
/****************************************************************************
1166
1205
*
1167
1206
*
@@ -1177,6 +1216,16 @@ static void error_cb (rd_kafka_t *rk, int err, const char *reason, void *opaque)
1177
1216
CallState * cs ;
1178
1217
1179
1218
cs = CallState_get (h );
1219
+
1220
+ /* If the client raised a fatal error we'll raise an exception
1221
+ * rather than calling the error callback. */
1222
+ if (err == RD_KAFKA_RESP_ERR__FATAL ) {
1223
+ char errstr [512 ];
1224
+ err = rd_kafka_fatal_error (rk , errstr , sizeof (errstr ));
1225
+ cfl_PyErr_Fatal (err , errstr );
1226
+ goto crash ;
1227
+ }
1228
+
1180
1229
if (!h -> error_cb ) {
1181
1230
/* No callback defined */
1182
1231
goto done ;
@@ -1189,6 +1238,7 @@ static void error_cb (rd_kafka_t *rk, int err, const char *reason, void *opaque)
1189
1238
if (result )
1190
1239
Py_DECREF (result );
1191
1240
else {
1241
+ crash :
1192
1242
CallState_crash (cs );
1193
1243
rd_kafka_yield (h -> rk );
1194
1244
}
@@ -1766,8 +1816,7 @@ rd_kafka_conf_t *common_conf_setup (rd_kafka_type_t ktype,
1766
1816
1767
1817
Py_DECREF (confdict );
1768
1818
1769
- if (h -> error_cb )
1770
- rd_kafka_conf_set_error_cb (conf , error_cb );
1819
+ rd_kafka_conf_set_error_cb (conf , error_cb );
1771
1820
1772
1821
if (h -> throttle_cb )
1773
1822
rd_kafka_conf_set_throttle_cb (conf , throttle_cb );
0 commit comments