1
1
// vim: set sts=4 sw=4 ts=4 et:
2
2
3
3
// Python.h includes pyconfig.h that unconditionally defines the
4
- // _POSIX_C_SOURCE and other constants, since the extension is compile with
4
+ // _POSIX_C_SOURCE and other constants, since the extension is compiled with
5
5
// -Werror the compilation fail if Python.h is included after any system level
6
6
// header
7
7
#include < Python.h>
@@ -16,8 +16,7 @@ namespace ctx = boost::context;
16
16
/* *
17
17
* This is a implementation of cooperatively scheduled M:1 fibers for python,
18
18
* the motivation for this project is to have the equivalent semantics as
19
- * greenlets but with no copying of the stack data and an implementation that
20
- * does not have assumptions about the stack.
19
+ * greenlets but with no copying of the stack data.
21
20
*
22
21
* The initial ideia was to use UNIX's makecontext() family of functions, this
23
22
* idea was dropped because the signal mask requires SYSCALLs to update the
@@ -34,8 +33,8 @@ namespace ctx = boost::context;
34
33
/* *
35
34
* Some notes:
36
35
*
37
- * mix does not keep track of a hierarchy of executaiton the same way that
38
- * greenlet does , this logic should be emulated in python.
36
+ * mix does not keep track of a hierarchy of execution like the greenlet
37
+ * library , this logic should be emulated in python.
39
38
*
40
39
* Currently there is no support for spagetthi/segmented stacks.
41
40
*
@@ -129,9 +128,27 @@ struct Fiber
129
128
**/
130
129
void first_call (intptr_t arguments_ptr) {
131
130
callback_t *callback;
131
+ PyObject* fiber;
132
132
133
133
callback = (callback_t *)arguments_ptr;
134
- PyObject_Call (callback->callback , callback->args , callback->kwds );
134
+
135
+ // PyObject_Call call will create a new frame object that will keep the
136
+ // variables alive, we don't need to increase the refcount
137
+ fiber = PyObject_Call (callback->callback , callback->args , callback->kwds );
138
+ // If we get here either the function returned or a exception was raised
139
+ // and not handled
140
+
141
+ // The fiber needs to exit to guarantee proper cleanup, otherwise callback
142
+ // could have references and keep objects alive.
143
+ if (fiber) {
144
+ // TODO: check the type of fiber and switch context
145
+ }
146
+
147
+ // Unlike greenlet we don't keep in the compiled code a chain of parent and
148
+ // child threads of execution, that means we don't have another stack to
149
+ // switch to and continue running, also we cannot raise an exception
150
+ // SystemExit exception because there is no stack to unwind, so just
151
+ // finalize the running interpreter.
135
152
136
153
#if PY_MAJOR_VERSION >= 3
137
154
PyObject *pystdout, *pystderr;
@@ -156,18 +173,25 @@ void first_call(intptr_t arguments_ptr) {
156
173
_PyObject_CallMethodId (pystdout, &PyId_flush, " " );
157
174
#endif
158
175
159
- printf (" mix: Fiber got to the end of stack\n " );
160
-
161
- // At this point we cannot raise an SystemExit exception because there is
162
- // no stack to unwind, so just finalize the running interpreter.
163
- //
164
- // XXX: this is probably wrong for python embedded
165
- Py_Finalize ();
166
- std::exit (1 );
176
+ // XXX: calling exit() is probably wrong for python embedded
177
+ // let the user know why we are exiting
178
+ // if (result == NULL) {
179
+ if (PyErr_Occurred () != NULL ) {
180
+ // PyObject *exc, *val, *tb;
181
+ // PyErr_Fetch(&exc, &val, &tb);
182
+ // PyErr_NormalizeException(&exc, &val, &c_tb);
183
+ PyErr_Print ();
184
+
185
+ // Calling Py_Finalize here will segfault
186
+ fprintf (stderr, " mix: Fiber got to the end of stack\n " );
187
+ std::exit (2 );
188
+ } else {
189
+ Py_Finalize ();
190
+ fprintf (stderr, " mix: Fiber got to the end of stack\n " );
191
+ std::exit (1 );
192
+ }
167
193
168
- // Unlike greenlet we don't keep in the compiled code a chain of parent and
169
- // child threads of execution, that means we don't have another stack to
170
- // continue running and beyond this point we will segfault.
194
+ // beyond this point the application will segfault
171
195
}
172
196
173
197
/* *
@@ -279,7 +303,7 @@ py::object py_context_switch(Fiber* origin, Fiber *target) {
279
303
return py_context_switch_args_kwds (origin, target, py::tuple (), py::dict ());
280
304
}
281
305
282
- BOOST_PYTHON_MODULE (mix )
306
+ BOOST_PYTHON_MODULE (fiber )
283
307
{
284
308
using namespace boost ::python;
285
309
0 commit comments