{"action":"opened","issue":{"url":"https://api.github.com/repos/gevent/gevent/issues/846","repository_url":"https://api.github.com/repos/gevent/gevent","labels_url":"https://api.github.com/repos/gevent/gevent/issues/846/labels{/name}","comments_url":"https://api.github.com/repos/gevent/gevent/issues/846/comments","events_url":"https://api.github.com/repos/gevent/gevent/issues/846/events","html_url":"https://github.com/gevent/gevent/issues/846","id":173804678,"number":846,"title":"Mask .kill() in greenlet","user":{"login":"sebastien-petitdemange","id":2430135,"avatar_url":"https://avatars.githubusercontent.com/u/2430135?v=3","gravatar_id":"","url":"https://api.github.com/users/sebastien-petitdemange","html_url":"https://github.com/sebastien-petitdemange","followers_url":"https://api.github.com/users/sebastien-petitdemange/followers","following_url":"https://api.github.com/users/sebastien-petitdemange/following{/other_user}","gists_url":"https://api.github.com/users/sebastien-petitdemange/gists{/gist_id}","starred_url":"https://api.github.com/users/sebastien-petitdemange/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sebastien-petitdemange/subscriptions","organizations_url":"https://api.github.com/users/sebastien-petitdemange/orgs","repos_url":"https://api.github.com/users/sebastien-petitdemange/repos","events_url":"https://api.github.com/users/sebastien-petitdemange/events{/privacy}","received_events_url":"https://api.github.com/users/sebastien-petitdemange/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-08-29T15:41:58Z","updated_at":"2016-08-29T15:41:58Z","closed_at":null,"body":"* gevent version: 1.1\r\n* Python version: 2.7\r\n* Operating System: Linux\r\n\r\n### Description:\r\n\r\nIn some cases, we would like to prevent `.kill()` to interrupt our critical code sections, something similar in spirit to `sigprocmask` but for greenlets.\r\n\r\nThere is a [question](http://stackoverflow.com/questions/39207303/how-to-mask-kill-on-a-gevent-greenlet-kill-protection) about that on stackoverflow.\r\n\r\n### Proposal:\r\n\r\nIn order to achieve this functionality here is the code we have implemented for now:\r\n\r\n```\r\nfrom gevent import greenlet\r\nimport gevent\r\nimport gevent.event\r\nfrom gevent.hub import Waiter\r\nimport time\r\n\r\nMASKED_GREENLETS = dict()\r\n\r\nclass KillMask:\r\n    def __init__(self):\r\n        self.__greenlet = gevent.getcurrent()\r\n\r\n    def __enter__(self):\r\n        self.__func, self.__exception, self.__waiter = None, None, None\r\n        MASKED_GREENLETS.setdefault(self.__greenlet, set()).add(self)\r\n\r\n    def __exit__(self, *args, **kwargs):\r\n        MASKED_GREENLETS[self.__greenlet].remove(self)\r\n        if MASKED_GREENLETS[self.__greenlet]:\r\n            return\r\n        if self.__func:\r\n            self.__greenlet.parent.loop.run_callback(self.__func, \r\n                                                     self.__greenlet,\r\n                                                     self.__exception, \r\n                                                     self.__waiter)\r\n\r\n    def set_kill(self, func, exception, waiter):\r\n        self.__func = func\r\n        self.__exception = exception\r\n        self.__waiter = waiter\r\n        \r\n\r\nsaved_kill = greenlet._kill\r\n\r\ndef _patched_kill(greenlet, exception, waiter) :\r\n    masks = MASKED_GREENLETS.get(greenlet)\r\n    if masks:\r\n        for m in masks:\r\n            m.set_kill(saved_kill, exception, waiter)\r\n    else:        \r\n        saved_kill(greenlet, exception, waiter)\r\n\r\ngreenlet._kill = _patched_kill\r\n```\r\n\r\nUsage:\r\n\r\n``` \r\ndef f() :\r\n    with KillMask():\r\n        t0 = time.time()\r\n        gevent.sleep(1)\r\n        with KillMask():\r\n          gevent.sleep(1)\r\n        print time.time()-t0\r\n    gevent.sleep(10)\r\n\r\nt = gevent.spawn(f)\r\ngevent.sleep(0.1)\r\nt.kill(ValueError)\r\n```\r\n\r\nWe can see the code under `KillMask` context manager is not interrupted by `.kill()`, but after it executed the \"protected\" code.\r\n\r\nWhat do you think of this ?\r\n\r\nAny advice to make this better or any work around would be really appreciated. We also need to make it work for `killall` and other possible cases ?\r\n\r\nThanks in advance for your attention !\r\n"}}
{"actor":{"display_login":"sebastien-petitdemange"}}