9
9
// 3. _ensure_fd_no_transport
10
10
// 4. _ensure_resolve
11
11
12
+ #include < iostream>
12
13
#include < boost/asio.hpp>
13
14
#include < boost/bind.hpp>
14
15
#include < boost/python.hpp>
@@ -52,7 +53,9 @@ void _sock_connect_cb(object pymod_socket, std::promise<void>& prom, std::future
52
53
if (err != object (0 )) {
53
54
// TODO: print the address
54
55
PyErr_SetString (PyExc_OSError, " Connect call failed {address}" );
56
+ throw_error_already_set ();
55
57
}
58
+ prom.set_value ();
56
59
}
57
60
catch (const error_already_set& e)
58
61
{
@@ -67,15 +70,10 @@ void _sock_connect_cb(object pymod_socket, std::promise<void>& prom, std::future
67
70
{
68
71
// raise
69
72
}
70
- else if (PyErr_ExceptionMatches (PyExc_BaseException))
71
- {
72
- PyErr_Clear ();
73
- prom.set_exception (std::current_exception ());
74
- }
75
73
else
76
74
{
77
75
PyErr_Clear ();
78
- prom.set_value ( );
76
+ prom.set_exception ( std::current_exception () );
79
77
}
80
78
}
81
79
}
@@ -91,6 +89,7 @@ void _sock_accept(event_loop& loop, std::promise<object>& prom, std::future<obje
91
89
conn = ret[0 ];
92
90
address = ret[1 ];
93
91
conn.attr (" setblocking" )(object (false ));
92
+ prom.set_value (make_tuple (conn, address));
94
93
}
95
94
catch (const error_already_set& e)
96
95
{
@@ -107,19 +106,27 @@ void _sock_accept(event_loop& loop, std::promise<object>& prom, std::future<obje
107
106
{
108
107
// raise
109
108
}
110
- else if (PyErr_ExceptionMatches (PyExc_BaseException))
111
- {
112
- PyErr_Clear ();
113
- prom.set_exception (std::current_exception ());
114
- }
115
109
else
116
110
{
117
111
PyErr_Clear ();
118
- prom.set_value ( make_tuple (conn, address ));
112
+ prom.set_exception ( std::current_exception ( ));
119
113
}
120
114
}
121
115
}
122
116
117
+ void _getaddrinfo_handler (object pymod_socket, std::promise<object>& prom,
118
+ object host, int port, int family, int type, int proto, int flags)
119
+ {
120
+ object res = pymod_socket.attr (" getaddrinfo" )(host, port, family, type, proto, flags);
121
+ prom.set_value (res);
122
+ }
123
+
124
+ void _getnameinfo_handler (object pymod_socket, std::promise<object>& prom, object sockaddr, int flags)
125
+ {
126
+ object res = pymod_socket.attr (" getnameinfo" )(sockaddr, flags);
127
+ prom.set_value (res);
128
+ }
129
+
123
130
}
124
131
125
132
void event_loop::_add_reader_or_writer (int fd, object f, int key)
@@ -237,6 +244,7 @@ void event_loop::sock_connect(object sock, object address)
237
244
try
238
245
{
239
246
sock.attr (" connect" )(address);
247
+ prom.set_value ();
240
248
}
241
249
catch (const error_already_set& e)
242
250
{
@@ -253,15 +261,10 @@ void event_loop::sock_connect(object sock, object address)
253
261
{
254
262
// raise
255
263
}
256
- else if (PyErr_ExceptionMatches (PyExc_BaseException))
257
- {
258
- PyErr_Clear ();
259
- prom.set_exception (std::current_exception ());
260
- }
261
264
else
262
265
{
263
266
PyErr_Clear ();
264
- prom.set_value ( );
267
+ prom.set_exception ( std::current_exception () );
265
268
}
266
269
}
267
270
fut.wait ();
@@ -279,6 +282,176 @@ object event_loop::sock_accept(object sock)
279
282
void event_loop::sock_sendfile (object sock, object file, int offset, int count, bool fallback)
280
283
{
281
284
PyErr_SetString (PyExc_NotImplementedError, " Not implemented!" );
285
+ throw_error_already_set ();
286
+ }
287
+
288
+ // TODO: implement this
289
+ void event_loop::start_tls (object transport, object protocol, object sslcontext,
290
+ bool server_side, object server_hostname, object ssl_handshake_timeout)
291
+ {
292
+ PyErr_SetString (PyExc_NotImplementedError, " Not implemented!" );
293
+ throw_error_already_set ();
294
+ }
295
+
296
+ object event_loop::getaddrinfo (object host, int port, int family, int type, int proto, int flags)
297
+ {
298
+ std::promise<object> prom;
299
+ std::future<object> fut = prom.get_future ();
300
+ call_soon (make_function (
301
+ bind (_getaddrinfo_handler, _pymod_socket, boost::ref (prom), host, port, family, type, proto, flags),
302
+ default_call_policies (),
303
+ boost::mpl::vector<void , object>()));
304
+ return fut.get ();
305
+ }
306
+
307
+ object event_loop::getnameinfo (object sockaddr, int flags)
308
+ {
309
+ std::promise<object> prom;
310
+ std::future<object> fut = prom.get_future ();
311
+ call_soon (make_function (
312
+ bind (_getnameinfo_handler, _pymod_socket, boost::ref (prom), sockaddr, flags),
313
+ default_call_policies (),
314
+ boost::mpl::vector<void , object>()));
315
+ return fut.get ();
316
+ }
317
+
318
+ void event_loop::default_exception_handler (object context)
319
+ {
320
+ object message = context.attr (" get" )(str (" message" ));
321
+ if (message == object ())
322
+ {
323
+ message = str (" Unhandled exception in event loop" );
324
+ }
325
+
326
+ object exception = context.attr (" get" )(str (" exception" ));
327
+ object exc_info;
328
+ if (exception != object ())
329
+ {
330
+ exc_info = make_tuple (exception .attr (" __class__" ), exception , exception .attr (" __traceback__" ));
331
+ }
332
+ else
333
+ {
334
+ exc_info = object (false );
335
+ }
336
+ if (!PyObject_IsTrue (context.attr (" __contains__" )(str (" source_traceback" )).ptr ()) &&
337
+ _exception_handler != object () &&
338
+ _exception_handler.attr (" _source_traceback" ) != object ())
339
+ {
340
+ context[" handle_traceback" ] = _exception_handler.attr (" _source_traceback" );
341
+ }
342
+
343
+ list log_lines;
344
+ log_lines.append (message);
345
+ list context_keys (context.attr (" keys" ));
346
+ context_keys.sort ();
347
+ for (int i = 0 ; i < len (context_keys); i++)
348
+ {
349
+ std::string key = extract<std::string>(context_keys[i]);
350
+ if (key == " message" || key == " exception" )
351
+ continue ;
352
+ str value (context[key]);
353
+ if (key == " source_traceback" )
354
+ {
355
+ str tb = str (" " ).join (_pymod_traceback.attr (" format_list" )(value));
356
+ value = str (" Object created at (most recent call last):\n " );
357
+ value += tb.rstrip ();
358
+ }
359
+ else if (key == " handle_traceback" )
360
+ {
361
+ str tb = str (" " ).join (_pymod_traceback.attr (" format_list" )(value));
362
+ value = str (" Handle created at (most recent call last):\n " );
363
+ value += tb.rstrip ();
364
+ }
365
+ else
366
+ {
367
+ value = str (value.attr (" __str__" )());
368
+ }
369
+ std::ostringstream stringStream;
370
+ stringStream << key << " : " << value;
371
+ log_lines.append (str (stringStream.str ()));
372
+ }
373
+ list args;
374
+ dict kwargs;
375
+ args.append (str (" \n " ).join (log_lines));
376
+ kwargs[" exc_info" ] = exc_info;
377
+ _pymod_logger.attr (" error" )(tuple (args), **kwargs);
378
+ }
379
+
380
+ void event_loop::call_exception_handler (object context)
381
+ {
382
+ if (_exception_handler == object ())
383
+ {
384
+ try
385
+ {
386
+ default_exception_handler (context);
387
+ }
388
+ catch (const error_already_set& e)
389
+ {
390
+ if (PyErr_ExceptionMatches (PyExc_SystemExit)
391
+ || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
392
+ {
393
+ // raise
394
+ }
395
+ else
396
+ {
397
+ PyErr_Clear ();
398
+ list args;
399
+ dict kwargs;
400
+ args.append (str (" Exception in default exception handler" ));
401
+ kwargs[" exc_info" ] = true ;
402
+ _pymod_logger.attr (" error" )(tuple (args), **kwargs);
403
+ }
404
+ }
405
+ }
406
+ else
407
+ {
408
+ try
409
+ {
410
+ _exception_handler (context);
411
+ }
412
+ catch (const error_already_set& e)
413
+ {
414
+ if (PyErr_ExceptionMatches (PyExc_SystemExit)
415
+ || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
416
+ {
417
+ // raise
418
+ }
419
+ else
420
+ {
421
+ PyObject *ptype, *pvalue, *ptraceback;
422
+ PyErr_Fetch (&ptype, &pvalue, &ptraceback);
423
+ PyErr_NormalizeException (&ptype, &pvalue, &ptraceback);
424
+ object type (handle<>(ptype));
425
+ object value (handle<>(pvalue));
426
+ object traceback (handle<>(ptraceback));
427
+ try
428
+ {
429
+ dict tmp_dict;
430
+ tmp_dict[" message" ] = str (" Unhandled error in exception handler" );
431
+ tmp_dict[" exception" ] = value;
432
+ tmp_dict[" context" ] = context;
433
+ default_exception_handler (tmp_dict);
434
+ }
435
+ catch (const error_already_set& e)
436
+ {
437
+ if (PyErr_ExceptionMatches (PyExc_SystemExit)
438
+ || PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
439
+ {
440
+ // raise
441
+ }
442
+ else
443
+ {
444
+ boost::python::list args;
445
+ boost::python::dict kwargs;
446
+ args.append (str (" Exception in default exception handler" ));
447
+ kwargs[" exc_info" ] = true ;
448
+ _pymod_logger.attr (" error" )(tuple (args), **kwargs);
449
+ }
450
+ }
451
+ }
452
+ }
453
+ }
282
454
}
283
455
456
+
284
457
}}}
0 commit comments