greenlet.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279
  1. /* vim:set noet ts=8 sw=8 : */
  2. #define GREENLET_MODULE
  3. #include "greenlet.h"
  4. #include "structmember.h"
  5. /* XXX major open bugs:
  6. XXX - no GC. Unfinished greenlets won't be deallocated if they
  7. XXX contain a cycle to themselves from anywhere in their frame stack.
  8. */
  9. /***********************************************************
  10. A PyGreenlet is a range of C stack addresses that must be
  11. saved and restored in such a way that the full range of the
  12. stack contains valid data when we switch to it.
  13. Stack layout for a greenlet:
  14. | ^^^ |
  15. | older data |
  16. | |
  17. stack_stop . |_______________|
  18. . | |
  19. . | greenlet data |
  20. . | in stack |
  21. . * |_______________| . . _____________ stack_copy + stack_saved
  22. . | | | |
  23. . | data | |greenlet data|
  24. . | unrelated | | saved |
  25. . | to | | in heap |
  26. stack_start . | this | . . |_____________| stack_copy
  27. | greenlet |
  28. | |
  29. | newer data |
  30. | vvv |
  31. Note that a greenlet's stack data is typically partly at its correct
  32. place in the stack, and partly saved away in the heap, but always in
  33. the above configuration: two blocks, the more recent one in the heap
  34. and the older one still in the stack (either block may be empty).
  35. Greenlets are chained: each points to the previous greenlet, which is
  36. the one that owns the data currently in the C stack above my
  37. stack_stop. The currently running greenlet is the first element of
  38. this chain. The main (initial) greenlet is the last one. Greenlets
  39. whose stack is entirely in the heap can be skipped from the chain.
  40. The chain is not related to execution order, but only to the order
  41. in which bits of C stack happen to belong to greenlets at a particular
  42. point in time.
  43. The main greenlet doesn't have a stack_stop: it is responsible for the
  44. complete rest of the C stack, and we don't know where it begins. We
  45. use (char*) -1, the largest possible address.
  46. States:
  47. stack_stop == NULL && stack_start == NULL: did not start yet
  48. stack_stop != NULL && stack_start == NULL: already finished
  49. stack_stop != NULL && stack_start != NULL: active
  50. The running greenlet's stack_start is undefined but not NULL.
  51. ***********************************************************/
  52. /*** global state ***/
  53. /* In the presence of multithreading, this is a bit tricky:
  54. - ts_current always store a reference to a greenlet, but it is
  55. not really the current greenlet after a thread switch occurred.
  56. - each *running* greenlet uses its run_info field to know which
  57. thread it is attached to. A greenlet can only run in the thread
  58. where it was created. This run_info is a ref to tstate->dict.
  59. - the thread state dict is used to save and restore ts_current,
  60. using the dictionary key 'ts_curkey'.
  61. */
  62. /* Python 2.3 support */
  63. #ifndef Py_VISIT
  64. #define Py_VISIT(o) \
  65. if (o) { \
  66. if ((err = visit((PyObject *)(o), arg))) { \
  67. return err; \
  68. } \
  69. }
  70. #endif /* !Py_VISIT */
  71. #ifndef Py_CLEAR
  72. #define Py_CLEAR(op) \
  73. do { \
  74. if (op) { \
  75. PyObject *tmp = (PyObject *)(op); \
  76. (op) = NULL; \
  77. Py_DECREF(tmp); \
  78. } \
  79. } while (0)
  80. #endif /* !Py_CLEAR */
  81. /* Python <= 2.5 support */
  82. #if PY_MAJOR_VERSION < 3
  83. #ifndef Py_REFCNT
  84. # define Py_REFCNT(ob) (((PyObject *) (ob))->ob_refcnt)
  85. #endif
  86. #ifndef Py_TYPE
  87. # define Py_TYPE(ob) (((PyObject *) (ob))->ob_type)
  88. #endif
  89. #endif
  90. extern PyTypeObject PyGreenlet_Type;
  91. /* The current greenlet in this thread state (holds a reference) */
  92. static PyGreenlet* ts_current = NULL;
  93. /* Holds a reference to the switching-from stack during the slp switch */
  94. static PyGreenlet* ts_origin = NULL;
  95. /* Holds a reference to the switching-to stack during the slp switch */
  96. static PyGreenlet* ts_target = NULL;
  97. /* NULL if error, otherwise args tuple to pass around during slp switch */
  98. static PyObject* ts_passaround_args = NULL;
  99. static PyObject* ts_passaround_kwargs = NULL;
  100. /***********************************************************/
  101. /* Thread-aware routines, switching global variables when needed */
  102. #define STATE_OK (ts_current->run_info == PyThreadState_GET()->dict \
  103. || !green_updatecurrent())
  104. static PyObject* ts_curkey;
  105. static PyObject* ts_delkey;
  106. static PyObject* PyExc_GreenletError;
  107. static PyObject* PyExc_GreenletExit;
  108. #undef GREENLET_USE_GC
  109. #ifdef GREENLET_USE_GC
  110. #define GREENLET_GC_FLAGS Py_TPFLAGS_HAVE_GC
  111. #define GREENLET_tp_alloc PyType_GenericAlloc
  112. #define GREENLET_tp_free PyObject_GC_Del
  113. #define GREENLET_tp_traverse green_traverse
  114. #define GREENLET_tp_clear green_clear
  115. #define GREENLET_tp_is_gc green_is_gc
  116. #else /* GREENLET_USE_GC */
  117. #define GREENLET_GC_FLAGS 0
  118. #define GREENLET_tp_alloc 0
  119. #define GREENLET_tp_free 0
  120. #define GREENLET_tp_traverse 0
  121. #define GREENLET_tp_clear 0
  122. #define GREENLET_tp_is_gc 0
  123. #endif /* !GREENLET_USE_GC */
  124. static PyGreenlet* green_create_main(void)
  125. {
  126. PyGreenlet* gmain;
  127. PyObject* dict = PyThreadState_GetDict();
  128. if (dict == NULL) {
  129. if (!PyErr_Occurred())
  130. PyErr_NoMemory();
  131. return NULL;
  132. }
  133. /* create the main greenlet for this thread */
  134. gmain = (PyGreenlet*) PyType_GenericAlloc(&PyGreenlet_Type, 0);
  135. if (gmain == NULL)
  136. return NULL;
  137. gmain->stack_start = (char*) 1;
  138. gmain->stack_stop = (char*) -1;
  139. gmain->run_info = dict;
  140. Py_INCREF(dict);
  141. #ifdef GREENLET_USE_GC
  142. printf("green_create_main %p\n", gmain);
  143. #endif
  144. return gmain;
  145. }
  146. static int green_updatecurrent(void)
  147. {
  148. PyThreadState* tstate;
  149. PyGreenlet* next;
  150. PyGreenlet* previous;
  151. PyObject* deleteme;
  152. /* save ts_current as the current greenlet of its own thread */
  153. previous = ts_current;
  154. if (PyDict_SetItem(previous->run_info, ts_curkey, (PyObject*) previous))
  155. return -1;
  156. /* get ts_current from the active tstate */
  157. tstate = PyThreadState_GET();
  158. if (tstate->dict && (next =
  159. (PyGreenlet*) PyDict_GetItem(tstate->dict, ts_curkey))) {
  160. /* found -- remove it, to avoid keeping a ref */
  161. Py_INCREF(next);
  162. if (PyDict_SetItem(tstate->dict, ts_curkey, Py_None))
  163. PyErr_Clear();
  164. }
  165. else {
  166. /* first time we see this tstate */
  167. next = green_create_main();
  168. if (next == NULL)
  169. return -1;
  170. }
  171. ts_current = next;
  172. Py_DECREF(previous);
  173. /* green_dealloc() cannot delete greenlets from other threads, so
  174. it stores them in the thread dict; delete them now. */
  175. deleteme = PyDict_GetItem(tstate->dict, ts_delkey);
  176. if (deleteme != NULL) {
  177. PyList_SetSlice(deleteme, 0, INT_MAX, NULL);
  178. }
  179. return 0;
  180. }
  181. static PyObject* green_statedict(PyGreenlet* g)
  182. {
  183. while (!PyGreenlet_STARTED(g))
  184. g = g->parent;
  185. return g->run_info;
  186. }
  187. /***********************************************************/
  188. static int g_save(PyGreenlet* g, char* stop)
  189. {
  190. /* Save more of g's stack into the heap -- at least up to 'stop'
  191. g->stack_stop |________|
  192. | |
  193. | __ stop . . . . .
  194. | | ==> . .
  195. |________| _______
  196. | | | |
  197. | | | |
  198. g->stack_start | | |_______| g->stack_copy
  199. */
  200. long sz1 = g->stack_saved;
  201. long sz2 = stop - g->stack_start;
  202. assert(g->stack_start != NULL);
  203. if (sz2 > sz1) {
  204. char* c = PyMem_Realloc(g->stack_copy, sz2);
  205. if (!c) {
  206. PyErr_NoMemory();
  207. return -1;
  208. }
  209. memcpy(c+sz1, g->stack_start+sz1, sz2-sz1);
  210. g->stack_copy = c;
  211. g->stack_saved = sz2;
  212. }
  213. return 0;
  214. }
  215. static void slp_restore_state(void)
  216. {
  217. PyGreenlet* g = ts_target;
  218. /* Restore the heap copy back into the C stack */
  219. if (g->stack_saved != 0) {
  220. memcpy(g->stack_start, g->stack_copy, g->stack_saved);
  221. PyMem_Free(g->stack_copy);
  222. g->stack_copy = NULL;
  223. g->stack_saved = 0;
  224. }
  225. if (ts_current->stack_stop == g->stack_stop)
  226. g->stack_prev = ts_current->stack_prev;
  227. else
  228. g->stack_prev = ts_current;
  229. }
  230. static int slp_save_state(char* stackref)
  231. {
  232. /* must free all the C stack up to target_stop */
  233. char* target_stop = ts_target->stack_stop;
  234. assert(ts_current->stack_saved == 0);
  235. if (ts_current->stack_start == NULL)
  236. ts_current = ts_current->stack_prev; /* not saved if dying */
  237. else
  238. ts_current->stack_start = stackref;
  239. while (ts_current->stack_stop < target_stop) {
  240. /* ts_current is entierely within the area to free */
  241. if (g_save(ts_current, ts_current->stack_stop))
  242. return -1; /* XXX */
  243. ts_current = ts_current->stack_prev;
  244. }
  245. if (ts_current != ts_target) {
  246. if (g_save(ts_current, target_stop))
  247. return -1; /* XXX */
  248. }
  249. return 0;
  250. }
  251. /*
  252. * the following macros are spliced into the OS/compiler
  253. * specific code, in order to simplify maintenance.
  254. */
  255. #define SLP_SAVE_STATE(stackref, stsizediff) \
  256. stackref += STACK_MAGIC; \
  257. if (slp_save_state((char*)stackref)) return -1; \
  258. if (!PyGreenlet_ACTIVE(ts_target)) return 1; \
  259. stsizediff = ts_target->stack_start - (char*)stackref
  260. #define SLP_RESTORE_STATE() \
  261. slp_restore_state()
  262. #define SLP_EVAL
  263. #include "slp_platformselect.h"
  264. #ifndef STACK_MAGIC
  265. #error "greenlet needs to be ported to this platform,\
  266. or teached how to detect your compiler properly."
  267. #endif /* !STACK_MAGIC */
  268. /* This is a trick to prevent the compiler from inlining or
  269. removing the frames */
  270. int (*_PyGreenlet_slp_switch) (void);
  271. int (*_PyGreenlet_switchstack) (void);
  272. void (*_PyGreenlet_initialstub) (void*);
  273. static int g_switchstack(void)
  274. {
  275. /* perform a stack switch according to some global variables
  276. that must be set before:
  277. - ts_current: current greenlet (holds a reference)
  278. - ts_target: greenlet to switch to
  279. - ts_passaround_args: NULL if PyErr_Occurred(),
  280. else a tuple of args sent to ts_target (holds a reference)
  281. - ts_passaround_kwargs: same as ts_passaround_args
  282. */
  283. int err;
  284. { /* save state */
  285. PyThreadState* tstate = PyThreadState_GET();
  286. ts_current->recursion_depth = tstate->recursion_depth;
  287. ts_current->top_frame = tstate->frame;
  288. }
  289. ts_origin = ts_current;
  290. err = _PyGreenlet_slp_switch();
  291. if (err < 0) { /* error */
  292. Py_XDECREF(ts_passaround_args);
  293. ts_passaround_args = NULL;
  294. Py_XDECREF(ts_passaround_kwargs);
  295. ts_passaround_kwargs = NULL;
  296. }
  297. else {
  298. PyThreadState* tstate = PyThreadState_GET();
  299. tstate->recursion_depth = ts_target->recursion_depth;
  300. tstate->frame = ts_target->top_frame;
  301. ts_target->top_frame = NULL;
  302. ts_current = ts_target;
  303. Py_INCREF(ts_target);
  304. Py_DECREF(ts_origin);
  305. }
  306. return err;
  307. }
  308. static PyObject *
  309. g_switch(PyGreenlet* target, PyObject* args, PyObject* kwargs)
  310. {
  311. /* _consumes_ a reference to the args tuple and kwargs dict,
  312. and return a new tuple reference */
  313. /* check ts_current */
  314. if (!STATE_OK) {
  315. Py_DECREF(args);
  316. Py_XDECREF(kwargs);
  317. return NULL;
  318. }
  319. if (green_statedict(target) != ts_current->run_info) {
  320. PyErr_SetString(PyExc_GreenletError,
  321. "cannot switch to a different thread");
  322. Py_DECREF(args);
  323. Py_XDECREF(kwargs);
  324. return NULL;
  325. }
  326. ts_passaround_args = args;
  327. ts_passaround_kwargs = kwargs;
  328. /* find the real target by ignoring dead greenlets,
  329. and if necessary starting a greenlet. */
  330. while (1) {
  331. if (PyGreenlet_ACTIVE(target)) {
  332. ts_target = target;
  333. _PyGreenlet_switchstack();
  334. break;
  335. }
  336. if (!PyGreenlet_STARTED(target)) {
  337. void* dummymarker;
  338. ts_target = target;
  339. _PyGreenlet_initialstub(&dummymarker);
  340. break;
  341. }
  342. target = target->parent;
  343. }
  344. /* We need to figure out what values to pass to the target greenlet
  345. based on the arguments that have been passed to greenlet.switch(). If
  346. switch() was just passed an arg tuple, then we'll just return that.
  347. If only keyword arguments were passed, then we'll pass the keyword
  348. argument dict. Otherwise, we'll create a tuple of (args, kwargs) and
  349. return both. */
  350. if (ts_passaround_kwargs == NULL)
  351. {
  352. return ts_passaround_args;
  353. }
  354. else if (PyDict_Size(ts_passaround_kwargs) == 0)
  355. {
  356. Py_DECREF(ts_passaround_kwargs);
  357. return ts_passaround_args;
  358. }
  359. else if (PySequence_Length(ts_passaround_args) == 0)
  360. {
  361. return ts_passaround_kwargs;
  362. }
  363. else
  364. {
  365. PyObject *tuple = PyTuple_New(2);
  366. PyTuple_SetItem(tuple, 0, ts_passaround_args);
  367. PyTuple_SetItem(tuple, 1, ts_passaround_kwargs);
  368. return tuple;
  369. }
  370. }
  371. static PyObject *
  372. g_handle_exit(PyObject *result)
  373. {
  374. if (result == NULL && PyErr_ExceptionMatches(PyExc_GreenletExit))
  375. {
  376. /* catch and ignore GreenletExit */
  377. PyObject *exc, *val, *tb;
  378. PyErr_Fetch(&exc, &val, &tb);
  379. if (val == NULL)
  380. {
  381. Py_INCREF(Py_None);
  382. val = Py_None;
  383. }
  384. result = val;
  385. Py_DECREF(exc);
  386. Py_XDECREF(tb);
  387. }
  388. if (result != NULL)
  389. {
  390. /* package the result into a 1-tuple */
  391. PyObject *r = result;
  392. result = PyTuple_New(1);
  393. if (result)
  394. {
  395. PyTuple_SET_ITEM(result, 0, r);
  396. }
  397. else
  398. {
  399. Py_DECREF(r);
  400. }
  401. }
  402. return result;
  403. }
  404. static void g_initialstub(void* mark)
  405. {
  406. int err;
  407. PyObject* o;
  408. /* ts_target.run is the object to call in the new greenlet */
  409. PyObject* run = PyObject_GetAttrString((PyObject*) ts_target, "run");
  410. if (run == NULL) {
  411. Py_XDECREF(ts_passaround_args);
  412. ts_passaround_args = NULL;
  413. Py_XDECREF(ts_passaround_kwargs);
  414. ts_passaround_kwargs = NULL;
  415. return;
  416. }
  417. /* now use run_info to store the statedict */
  418. o = ts_target->run_info;
  419. ts_target->run_info = green_statedict(ts_target->parent);
  420. Py_INCREF(ts_target->run_info);
  421. Py_XDECREF(o);
  422. /* start the greenlet */
  423. ts_target->stack_start = NULL;
  424. ts_target->stack_stop = (char*) mark;
  425. if (ts_current->stack_start == NULL) {
  426. /* ts_current is dying */
  427. ts_target->stack_prev = ts_current->stack_prev;
  428. }
  429. else {
  430. ts_target->stack_prev = ts_current;
  431. }
  432. ts_target->top_frame = NULL;
  433. ts_target->recursion_depth = PyThreadState_GET()->recursion_depth;
  434. err = _PyGreenlet_switchstack();
  435. /* returns twice!
  436. The 1st time with err=1: we are in the new greenlet
  437. The 2nd time with err=0: back in the caller's greenlet
  438. */
  439. if (err == 1) {
  440. /* in the new greenlet */
  441. PyObject* args;
  442. PyObject* kwargs;
  443. PyObject* result;
  444. PyGreenlet* ts_self = ts_current;
  445. ts_self->stack_start = (char*) 1; /* running */
  446. args = ts_passaround_args;
  447. kwargs = ts_passaround_kwargs;
  448. if (args == NULL) /* pending exception */
  449. result = NULL;
  450. else {
  451. /* call g.run(*args, **kwargs) */
  452. result = PyEval_CallObjectWithKeywords(
  453. run, args, kwargs);
  454. Py_DECREF(args);
  455. Py_XDECREF(kwargs);
  456. }
  457. Py_DECREF(run);
  458. result = g_handle_exit(result);
  459. /* jump back to parent */
  460. ts_self->stack_start = NULL; /* dead */
  461. g_switch(ts_self->parent, result, NULL);
  462. /* must not return from here! */
  463. PyErr_WriteUnraisable((PyObject *) ts_self);
  464. Py_FatalError("greenlets cannot continue");
  465. }
  466. /* back in the parent */
  467. }
  468. /***********************************************************/
  469. static PyObject* green_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  470. {
  471. PyObject* o;
  472. if (!STATE_OK)
  473. return NULL;
  474. o = type->tp_alloc(type, 0);
  475. if (o != NULL) {
  476. Py_INCREF(ts_current);
  477. ((PyGreenlet*) o)->parent = ts_current;
  478. }
  479. #ifdef GREENLET_USE_GC
  480. printf("green_new %p\n", o);
  481. #endif
  482. return o;
  483. }
  484. static int green_setrun(PyGreenlet* self, PyObject* nparent, void* c);
  485. static int green_setparent(PyGreenlet* self, PyObject* nparent, void* c);
  486. static int green_init(PyGreenlet *self, PyObject *args, PyObject *kwargs)
  487. {
  488. PyObject *run = NULL;
  489. PyObject* nparent = NULL;
  490. static char *kwlist[] = {"run", "parent", 0};
  491. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO:green", kwlist,
  492. &run, &nparent))
  493. return -1;
  494. if (run != NULL) {
  495. if (green_setrun(self, run, NULL))
  496. return -1;
  497. }
  498. if (nparent != NULL)
  499. return green_setparent(self, nparent, NULL);
  500. return 0;
  501. }
  502. static int kill_greenlet(PyGreenlet* self)
  503. {
  504. /* Cannot raise an exception to kill the greenlet if
  505. it is not running in the same thread! */
  506. #ifdef GREENLET_USE_GC
  507. printf("kill_greenlet %p\n", self);
  508. #endif
  509. if (self->run_info == PyThreadState_GET()->dict) {
  510. /* The dying greenlet cannot be a parent of ts_current
  511. because the 'parent' field chain would hold a
  512. reference */
  513. PyObject* result;
  514. if (!STATE_OK) {
  515. return -1;
  516. }
  517. Py_INCREF(ts_current);
  518. self->parent = ts_current;
  519. /* Send the greenlet a GreenletExit exception. */
  520. PyErr_SetNone(PyExc_GreenletExit);
  521. result = g_switch(self, NULL, NULL);
  522. if (result == NULL)
  523. return -1;
  524. Py_DECREF(result);
  525. return 0;
  526. }
  527. else {
  528. /* Not the same thread! Temporarily save the greenlet
  529. into its thread's ts_delkey list. */
  530. PyObject* lst;
  531. lst = PyDict_GetItem(self->run_info, ts_delkey);
  532. if (lst == NULL) {
  533. lst = PyList_New(0);
  534. if (lst == NULL || PyDict_SetItem(self->run_info,
  535. ts_delkey, lst) < 0)
  536. return -1;
  537. }
  538. if (PyList_Append(lst, (PyObject*) self) < 0)
  539. return -1;
  540. if (!STATE_OK) /* to force ts_delkey to be reconsidered */
  541. return -1;
  542. return 0;
  543. }
  544. }
  545. #ifdef GREENLET_USE_GC
  546. static int
  547. green_traverse(PyGreenlet *so, visitproc visit, void *arg)
  548. {
  549. printf("green_traverse %p\n", so);
  550. Py_VISIT((PyObject*)so->run_info);
  551. Py_VISIT((PyObject*)so->parent);
  552. Py_VISIT((PyObject*)so->top_frame);
  553. Py_VISIT((PyObject*)so->stack_prev);
  554. Py_VISIT((PyObject*)so->parent);
  555. return 0;
  556. }
  557. static int green_is_gc(PyGreenlet* self)
  558. {
  559. int rval;
  560. rval = (self->stack_stop == ((char *)-1)) ? 0 : 1;
  561. printf("green_is_gc %p = %d\n", self, rval);
  562. return rval;
  563. }
  564. static int green_clear(PyGreenlet* self)
  565. {
  566. printf("green_clear %p run_info %p\n", self, self->run_info);
  567. if (PyGreenlet_ACTIVE(self))
  568. return kill_greenlet(self);
  569. return 0;
  570. }
  571. #endif
  572. static void green_dealloc(PyGreenlet* self)
  573. {
  574. PyObject *error_type, *error_value, *error_traceback;
  575. #ifdef GREENLET_USE_GC
  576. printf("green_dealloc %p\n", self);
  577. PyObject_GC_UnTrack((PyObject *)self);
  578. Py_TRASHCAN_SAFE_BEGIN(self);
  579. #endif /* GREENLET_USE_GC */
  580. Py_CLEAR(self->parent);
  581. if (PyGreenlet_ACTIVE(self)) {
  582. /* Hacks hacks hacks copied from instance_dealloc() */
  583. /* Temporarily resurrect the greenlet. */
  584. assert(Py_REFCNT(self) == 0);
  585. Py_REFCNT(self) = 1;
  586. /* Save the current exception, if any. */
  587. PyErr_Fetch(&error_type, &error_value, &error_traceback);
  588. if (kill_greenlet(self) < 0) {
  589. PyErr_WriteUnraisable((PyObject*) self);
  590. /* XXX what else should we do? */
  591. }
  592. /* Restore the saved exception. */
  593. PyErr_Restore(error_type, error_value, error_traceback);
  594. /* Undo the temporary resurrection; can't use DECREF here,
  595. * it would cause a recursive call.
  596. */
  597. assert(Py_REFCNT(self) > 0);
  598. --Py_REFCNT(self);
  599. if (Py_REFCNT(self) == 0 && PyGreenlet_ACTIVE(self)) {
  600. /* Not resurrected, but still not dead!
  601. XXX what else should we do? we complain. */
  602. PyObject* f = PySys_GetObject("stderr");
  603. if (f != NULL) {
  604. PyFile_WriteString("GreenletExit did not kill ",
  605. f);
  606. PyFile_WriteObject((PyObject*) self, f, 0);
  607. PyFile_WriteString("\n", f);
  608. }
  609. Py_INCREF(self); /* leak! */
  610. }
  611. if (Py_REFCNT(self) != 0) {
  612. /* Resurrected! */
  613. int refcnt = Py_REFCNT(self);
  614. _Py_NewReference((PyObject*) self);
  615. #ifdef GREENLET_USE_GC
  616. PyObject_GC_Track((PyObject *)self);
  617. #endif
  618. Py_REFCNT(self) = refcnt;
  619. #ifdef COUNT_ALLOCS
  620. --Py_TYPE(self)->tp_frees;
  621. --Py_TYPE(self)->tp_allocs;
  622. #endif /* COUNT_ALLOCS */
  623. goto green_dealloc_end;
  624. }
  625. }
  626. if (self->weakreflist != NULL)
  627. PyObject_ClearWeakRefs((PyObject *) self);
  628. Py_CLEAR(self->run_info);
  629. Py_TYPE(self)->tp_free((PyObject*) self);
  630. green_dealloc_end:
  631. #ifdef GREENLET_USE_GC
  632. Py_TRASHCAN_SAFE_END(self);
  633. #endif /* GREENLET_USE_GC */
  634. return;
  635. }
  636. static PyObject* single_result(PyObject* results)
  637. {
  638. if (results != NULL && PyTuple_Check(results) &&
  639. PyTuple_GET_SIZE(results) == 1) {
  640. PyObject *result = PyTuple_GET_ITEM(results, 0);
  641. Py_INCREF(result);
  642. Py_DECREF(results);
  643. return result;
  644. }
  645. else
  646. return results;
  647. }
  648. static PyObject *
  649. throw_greenlet(PyGreenlet *self, PyObject *typ, PyObject *val, PyObject *tb)
  650. {
  651. /* Note: _consumes_ a reference to typ, val, tb */
  652. PyObject *result = NULL;
  653. PyErr_Restore(typ, val, tb);
  654. if (PyGreenlet_STARTED(self) && !PyGreenlet_ACTIVE(self))
  655. {
  656. /* dead greenlet: turn GreenletExit into a regular return */
  657. result = g_handle_exit(result);
  658. }
  659. return single_result(g_switch(self, result, NULL));
  660. }
  661. PyDoc_STRVAR(green_switch_doc,
  662. "switch(*args, **kwargs)\n\
  663. \n\
  664. Switch execution to this greenlet.\n\
  665. \n\
  666. If this greenlet has never been run, then this greenlet\n\
  667. will be switched to using the body of self.run(*args, **kwargs).\n\
  668. \n\
  669. If the greenlet is active (has been run, but was switch()'ed\n\
  670. out before leaving its run function), then this greenlet will\n\
  671. be resumed and the return value to its switch call will be\n\
  672. None if no arguments are given, the given argument if one\n\
  673. argument is given, or the args tuple and keyword args dict if\n\
  674. multiple arguments are given.\n\
  675. \n\
  676. If the greenlet is dead, or is the current greenlet then this\n\
  677. function will simply return the arguments using the same rules as\n\
  678. above.");
  679. static PyObject* green_switch(
  680. PyGreenlet* self,
  681. PyObject* args,
  682. PyObject* kwargs)
  683. {
  684. Py_INCREF(args);
  685. Py_XINCREF(kwargs);
  686. return single_result(g_switch(self, args, kwargs));
  687. }
  688. /* Macros required to support Python < 2.6 for green_throw() */
  689. #ifndef PyExceptionClass_Check
  690. # define PyExceptionClass_Check PyClass_Check
  691. #endif
  692. #ifndef PyExceptionInstance_Check
  693. # define PyExceptionInstance_Check PyInstance_Check
  694. #endif
  695. #ifndef PyExceptionInstance_Class
  696. # define PyExceptionInstance_Class(x) \
  697. ((PyObject *) ((PyInstanceObject *)(x))->in_class)
  698. #endif
  699. PyDoc_STRVAR(green_throw_doc,
  700. "Switches execution to the greenlet ``g``, but immediately raises the\n"
  701. "given exception in ``g``. If no argument is provided, the exception\n"
  702. "defaults to ``greenlet.GreenletExit``. The normal exception\n"
  703. "propagation rules apply, as described above. Note that calling this\n"
  704. "method is almost equivalent to the following::\n"
  705. "\n"
  706. " def raiser():\n"
  707. " raise typ, val, tb\n"
  708. " g_raiser = greenlet(raiser, parent=g)\n"
  709. " g_raiser.switch()\n"
  710. "\n"
  711. "except that this trick does not work for the\n"
  712. "``greenlet.GreenletExit`` exception, which would not propagate\n"
  713. "from ``g_raiser`` to ``g``.\n");
  714. static PyObject *
  715. green_throw(PyGreenlet *self, PyObject *args)
  716. {
  717. PyObject *typ = PyExc_GreenletExit;
  718. PyObject *val = NULL;
  719. PyObject *tb = NULL;
  720. if (!PyArg_ParseTuple(args, "|OOO:throw", &typ, &val, &tb))
  721. {
  722. return NULL;
  723. }
  724. /* First, check the traceback argument, replacing None, with NULL */
  725. if (tb == Py_None)
  726. {
  727. tb = NULL;
  728. }
  729. else if (tb != NULL && !PyTraceBack_Check(tb))
  730. {
  731. PyErr_SetString(
  732. PyExc_TypeError,
  733. "throw() third argument must be a traceback object");
  734. return NULL;
  735. }
  736. Py_INCREF(typ);
  737. Py_XINCREF(val);
  738. Py_XINCREF(tb);
  739. if (PyExceptionClass_Check(typ))
  740. {
  741. PyErr_NormalizeException(&typ, &val, &tb);
  742. }
  743. else if (PyExceptionInstance_Check(typ))
  744. {
  745. /* Raising an instance. The value should be a dummy. */
  746. if (val && val != Py_None)
  747. {
  748. PyErr_SetString(
  749. PyExc_TypeError,
  750. "instance exception may not have a separate value");
  751. goto failed_throw;
  752. }
  753. else
  754. {
  755. /* Normalize to raise <class>, <instance> */
  756. Py_XDECREF(val);
  757. val = typ;
  758. typ = PyExceptionInstance_Class(typ);
  759. Py_INCREF(typ);
  760. }
  761. }
  762. else
  763. {
  764. /* Not something you can raise. throw() fails. */
  765. PyErr_Format(
  766. PyExc_TypeError,
  767. "exceptions must be classes, or instances, not %s",
  768. Py_TYPE(typ)->tp_name);
  769. goto failed_throw;
  770. }
  771. return throw_greenlet(self, typ, val, tb);
  772. failed_throw:
  773. /* Didn't use our arguments, so restore their original refcounts */
  774. Py_DECREF(typ);
  775. Py_XDECREF(val);
  776. Py_XDECREF(tb);
  777. return NULL;
  778. }
  779. static int green_bool(PyGreenlet* self)
  780. {
  781. return PyGreenlet_ACTIVE(self);
  782. }
  783. static PyObject* green_getdead(PyGreenlet* self, void* c)
  784. {
  785. PyObject* res;
  786. if (PyGreenlet_ACTIVE(self) || !PyGreenlet_STARTED(self))
  787. res = Py_False;
  788. else
  789. res = Py_True;
  790. Py_INCREF(res);
  791. return res;
  792. }
  793. static PyObject* green_getrun(PyGreenlet* self, void* c)
  794. {
  795. if (PyGreenlet_STARTED(self) || self->run_info == NULL) {
  796. PyErr_SetString(PyExc_AttributeError, "run");
  797. return NULL;
  798. }
  799. Py_INCREF(self->run_info);
  800. return self->run_info;
  801. }
  802. static int green_setrun(PyGreenlet* self, PyObject* nrun, void* c)
  803. {
  804. PyObject* o;
  805. if (PyGreenlet_STARTED(self)) {
  806. PyErr_SetString(PyExc_AttributeError,
  807. "run cannot be set "
  808. "after the start of the greenlet");
  809. return -1;
  810. }
  811. o = self->run_info;
  812. self->run_info = nrun;
  813. Py_XINCREF(nrun);
  814. Py_XDECREF(o);
  815. return 0;
  816. }
  817. static PyObject* green_getparent(PyGreenlet* self, void* c)
  818. {
  819. PyObject* result = self->parent ? (PyObject*) self->parent : Py_None;
  820. Py_INCREF(result);
  821. return result;
  822. }
  823. static int green_setparent(PyGreenlet* self, PyObject* nparent, void* c)
  824. {
  825. PyGreenlet* p;
  826. if (nparent == NULL) {
  827. PyErr_SetString(PyExc_AttributeError, "can't delete attribute");
  828. return -1;
  829. }
  830. if (!PyGreenlet_Check(nparent)) {
  831. PyErr_SetString(PyExc_TypeError, "parent must be a greenlet");
  832. return -1;
  833. }
  834. for (p=(PyGreenlet*) nparent; p; p=p->parent) {
  835. if (p == self) {
  836. PyErr_SetString(PyExc_ValueError, "cyclic parent chain");
  837. return -1;
  838. }
  839. }
  840. p = self->parent;
  841. self->parent = (PyGreenlet*) nparent;
  842. Py_INCREF(nparent);
  843. Py_XDECREF(p);
  844. return 0;
  845. }
  846. static PyObject* green_getframe(PyGreenlet* self, void* c)
  847. {
  848. PyObject* result = self->top_frame ? (PyObject*) self->top_frame : Py_None;
  849. Py_INCREF(result);
  850. return result;
  851. }
  852. /*****************************************************************************
  853. * C interface
  854. *
  855. * These are exported using the CObject API
  856. */
  857. static PyGreenlet *
  858. PyGreenlet_GetCurrent(void)
  859. {
  860. if (!STATE_OK) {
  861. return NULL;
  862. }
  863. Py_INCREF(ts_current);
  864. return ts_current;
  865. }
  866. static int
  867. PyGreenlet_SetParent(PyGreenlet *g, PyGreenlet *nparent)
  868. {
  869. if (!STATE_OK) {
  870. return -1;
  871. }
  872. if (!PyGreenlet_Check(g)) {
  873. PyErr_SetString(PyExc_TypeError, "parent must be a greenlet");
  874. return -1;
  875. }
  876. return green_setparent((PyGreenlet*) g, (PyObject *) nparent, NULL);
  877. }
  878. static PyGreenlet *
  879. PyGreenlet_New(PyObject *run, PyGreenlet *parent)
  880. {
  881. PyGreenlet* g = NULL;
  882. g = (PyGreenlet *) PyType_GenericAlloc(&PyGreenlet_Type, 0);
  883. if (g == NULL) {
  884. return NULL;
  885. }
  886. if (run != NULL) {
  887. Py_INCREF(run);
  888. g->run_info = run;
  889. }
  890. if (parent == NULL) {
  891. parent = PyGreenlet_GetCurrent();
  892. }
  893. PyGreenlet_SetParent(g, parent);
  894. return g;
  895. }
  896. static PyObject *
  897. PyGreenlet_Switch(PyGreenlet *g, PyObject *args, PyObject *kwargs)
  898. {
  899. PyGreenlet *self = (PyGreenlet *) g;
  900. if (!PyGreenlet_Check(self)) {
  901. PyErr_BadArgument();
  902. return NULL;
  903. }
  904. if (args == NULL) {
  905. args = Py_BuildValue("()");
  906. }
  907. else {
  908. Py_INCREF(args);
  909. }
  910. if (kwargs != NULL && PyDict_Check(kwargs)) {
  911. Py_INCREF(kwargs);
  912. }
  913. else {
  914. kwargs = NULL;
  915. }
  916. return single_result(g_switch(self, args, kwargs));
  917. }
  918. static PyObject *
  919. PyGreenlet_Throw(PyGreenlet *self, PyObject *typ, PyObject *val, PyObject *tb)
  920. {
  921. if (!PyGreenlet_Check(self)) {
  922. PyErr_BadArgument();
  923. return NULL;
  924. }
  925. return throw_greenlet(self, typ, val, tb);
  926. }
  927. /** End C API ****************************************************************/
  928. static PyMethodDef green_methods[] = {
  929. {"switch", (PyCFunction)green_switch,
  930. METH_VARARGS | METH_KEYWORDS, green_switch_doc},
  931. {"throw", (PyCFunction)green_throw, METH_VARARGS, green_throw_doc},
  932. {NULL, NULL} /* sentinel */
  933. };
  934. static PyGetSetDef green_getsets[] = {
  935. {"run", (getter)green_getrun,
  936. (setter)green_setrun, /*XXX*/ NULL},
  937. {"parent", (getter)green_getparent,
  938. (setter)green_setparent, /*XXX*/ NULL},
  939. {"gr_frame", (getter)green_getframe,
  940. NULL, /*XXX*/ NULL},
  941. {"dead", (getter)green_getdead,
  942. NULL, /*XXX*/ NULL},
  943. {NULL}
  944. };
  945. static PyNumberMethods green_as_number = {
  946. NULL, /* nb_add */
  947. NULL, /* nb_subtract */
  948. NULL, /* nb_multiply */
  949. #if PY_MAJOR_VERSION < 3
  950. NULL, /* nb_divide */
  951. #endif
  952. NULL, /* nb_remainder */
  953. NULL, /* nb_divmod */
  954. NULL, /* nb_power */
  955. NULL, /* nb_negative */
  956. NULL, /* nb_positive */
  957. NULL, /* nb_absolute */
  958. (inquiry)green_bool, /* nb_bool */
  959. };
  960. PyTypeObject PyGreenlet_Type = {
  961. #if PY_MAJOR_VERSION >= 3
  962. PyVarObject_HEAD_INIT(NULL, 0)
  963. #else
  964. PyObject_HEAD_INIT(NULL)
  965. 0, /* ob_size */
  966. #endif
  967. "greenlet.greenlet", /* tp_name */
  968. sizeof(PyGreenlet), /* tp_basicsize */
  969. 0, /* tp_itemsize */
  970. /* methods */
  971. (destructor)green_dealloc, /* tp_dealloc */
  972. 0, /* tp_print */
  973. 0, /* tp_getattr */
  974. 0, /* tp_setattr */
  975. 0, /* tp_compare */
  976. 0, /* tp_repr */
  977. &green_as_number, /* tp_as _number*/
  978. 0, /* tp_as _sequence*/
  979. 0, /* tp_as _mapping*/
  980. 0, /* tp_hash */
  981. 0, /* tp_call */
  982. 0, /* tp_str */
  983. 0, /* tp_getattro */
  984. 0, /* tp_setattro */
  985. 0, /* tp_as_buffer*/
  986. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | GREENLET_GC_FLAGS, /* tp_flags */
  987. "greenlet(run=None, parent=None) -> greenlet\n\n"
  988. "Creates a new greenlet object (without running it).\n\n"
  989. " - *run* -- The callable to invoke.\n"
  990. " - *parent* -- The parent greenlet. The default is the current "
  991. "greenlet.", /* tp_doc */
  992. (traverseproc)GREENLET_tp_traverse, /* tp_traverse */
  993. (inquiry)GREENLET_tp_clear, /* tp_clear */
  994. 0, /* tp_richcompare */
  995. offsetof(PyGreenlet, weakreflist), /* tp_weaklistoffset */
  996. 0, /* tp_iter */
  997. 0, /* tp_iternext */
  998. green_methods, /* tp_methods */
  999. 0, /* tp_members */
  1000. green_getsets, /* tp_getset */
  1001. 0, /* tp_base */
  1002. 0, /* tp_dict */
  1003. 0, /* tp_descr_get */
  1004. 0, /* tp_descr_set */
  1005. 0, /* tp_dictoffset */
  1006. (initproc)green_init, /* tp_init */
  1007. GREENLET_tp_alloc, /* tp_alloc */
  1008. green_new, /* tp_new */
  1009. GREENLET_tp_free, /* tp_free */
  1010. (inquiry)GREENLET_tp_is_gc, /* tp_is_gc */
  1011. };
  1012. /* XXX need GC support */
  1013. static PyObject* mod_getcurrent(PyObject* self)
  1014. {
  1015. if (!STATE_OK)
  1016. return NULL;
  1017. Py_INCREF(ts_current);
  1018. return (PyObject*) ts_current;
  1019. }
  1020. static PyMethodDef GreenMethods[] = {
  1021. {"getcurrent", (PyCFunction)mod_getcurrent, METH_NOARGS, /*XXX*/ NULL},
  1022. {NULL, NULL} /* Sentinel */
  1023. };
  1024. static char* copy_on_greentype[] = {
  1025. "getcurrent", "error", "GreenletExit", NULL
  1026. };
  1027. #if PY_MAJOR_VERSION >= 3
  1028. #define INITERROR return NULL
  1029. static struct PyModuleDef greenlet_module_def = {
  1030. PyModuleDef_HEAD_INIT,
  1031. "greenlet",
  1032. NULL,
  1033. -1,
  1034. GreenMethods,
  1035. };
  1036. PyObject *
  1037. PyInit_greenlet(void)
  1038. #else
  1039. #define INITERROR return
  1040. void initgreenlet(void)
  1041. #endif
  1042. {
  1043. PyObject* m = NULL;
  1044. char** p = NULL;
  1045. PyObject *c_api_object;
  1046. static void *_PyGreenlet_API[PyGreenlet_API_pointers];
  1047. _PyGreenlet_switchstack = g_switchstack;
  1048. _PyGreenlet_slp_switch = slp_switch;
  1049. _PyGreenlet_initialstub = g_initialstub;
  1050. #if PY_MAJOR_VERSION >= 3
  1051. m = PyModule_Create(&greenlet_module_def);
  1052. #else
  1053. m = Py_InitModule("greenlet", GreenMethods);
  1054. #endif
  1055. if (m == NULL)
  1056. {
  1057. INITERROR;
  1058. }
  1059. if (PyModule_AddStringConstant(m, "__version__", GREENLET_VERSION) < 0)
  1060. {
  1061. INITERROR;
  1062. }
  1063. #if PY_MAJOR_VERSION >= 3
  1064. ts_curkey = PyUnicode_InternFromString("__greenlet_ts_curkey");
  1065. ts_delkey = PyUnicode_InternFromString("__greenlet_ts_delkey");
  1066. #else
  1067. ts_curkey = PyString_InternFromString("__greenlet_ts_curkey");
  1068. ts_delkey = PyString_InternFromString("__greenlet_ts_delkey");
  1069. #endif
  1070. if (ts_curkey == NULL || ts_delkey == NULL)
  1071. {
  1072. INITERROR;
  1073. }
  1074. if (PyType_Ready(&PyGreenlet_Type) < 0)
  1075. {
  1076. INITERROR;
  1077. }
  1078. PyExc_GreenletError = PyErr_NewException("greenlet.error", NULL, NULL);
  1079. if (PyExc_GreenletError == NULL)
  1080. {
  1081. INITERROR;
  1082. }
  1083. PyExc_GreenletExit = PyErr_NewException("greenlet.GreenletExit",
  1084. NULL, NULL);
  1085. if (PyExc_GreenletExit == NULL)
  1086. {
  1087. INITERROR;
  1088. }
  1089. ts_current = green_create_main();
  1090. if (ts_current == NULL)
  1091. {
  1092. INITERROR;
  1093. }
  1094. Py_INCREF(&PyGreenlet_Type);
  1095. PyModule_AddObject(m, "greenlet", (PyObject*) &PyGreenlet_Type);
  1096. Py_INCREF(PyExc_GreenletError);
  1097. PyModule_AddObject(m, "error", PyExc_GreenletError);
  1098. Py_INCREF(PyExc_GreenletExit);
  1099. PyModule_AddObject(m, "GreenletExit", PyExc_GreenletExit);
  1100. #ifdef GREENLET_USE_GC
  1101. PyModule_AddObject(m, "GREENLET_USE_GC", PyBool_FromLong(1));
  1102. #else
  1103. PyModule_AddObject(m, "GREENLET_USE_GC", PyBool_FromLong(0));
  1104. #endif
  1105. /* also publish module-level data as attributes of the greentype. */
  1106. for (p=copy_on_greentype; *p; p++) {
  1107. PyObject* o = PyObject_GetAttrString(m, *p);
  1108. if (!o) continue;
  1109. PyDict_SetItemString(PyGreenlet_Type.tp_dict, *p, o);
  1110. Py_DECREF(o);
  1111. }
  1112. /*
  1113. * Expose C API
  1114. */
  1115. /* types */
  1116. _PyGreenlet_API[PyGreenlet_Type_NUM] = (void *) &PyGreenlet_Type;
  1117. /* exceptions */
  1118. _PyGreenlet_API[PyExc_GreenletError_NUM] = (void *) PyExc_GreenletError;
  1119. _PyGreenlet_API[PyExc_GreenletExit_NUM] = (void *) PyExc_GreenletExit;
  1120. /* methods */
  1121. _PyGreenlet_API[PyGreenlet_New_NUM] = (void *) PyGreenlet_New;
  1122. _PyGreenlet_API[PyGreenlet_GetCurrent_NUM] =
  1123. (void *) PyGreenlet_GetCurrent;
  1124. _PyGreenlet_API[PyGreenlet_Throw_NUM] = (void *) PyGreenlet_Throw;
  1125. _PyGreenlet_API[PyGreenlet_Switch_NUM] = (void *) PyGreenlet_Switch;
  1126. _PyGreenlet_API[PyGreenlet_SetParent_NUM] =
  1127. (void *) PyGreenlet_SetParent;
  1128. c_api_object = PyCObject_FromVoidPtr((void *) _PyGreenlet_API, NULL);
  1129. if (c_api_object != NULL)
  1130. {
  1131. PyModule_AddObject(m, "_C_API", c_api_object);
  1132. }
  1133. #if PY_MAJOR_VERSION >= 3
  1134. return m;
  1135. #endif
  1136. }