Presentation is loading. Please wait.

Presentation is loading. Please wait.

Why killing tasklets is good practice

Similar presentations

Presentation on theme: "Why killing tasklets is good practice"— Presentation transcript:

1 Why killing tasklets is good practice
Death to tasklets! Why killing tasklets is good practice

2 History Multiprocessing Multi-threading
Master process spawns off multiple processes Waits for them to finish Multi-threading Within a process, threads are spawned „main thread“ waits for their results

3 Start Stop A typical problem Main „process“ starts a „server process“
Main process wants to stop server process Start Stop Get request Process request Finish request

4 How? Ask the server to quit Kill it with death!
Message passing is nice Politeness is nice Good and tidy programing practice Kill it with death! Asynchronous (where does it get killed?) Impolite (will it clean up?) Impossible (what API is that?)

5 MEGADEATH Processes: Unix signals: Windows:
SIGINT, can cause system calls to fail with an EINTERRUPTED error code. SIGKILL or SIGTERM just kills them outright Files are closed, memory is released. Buffers are not flushed Windows: TerminateProcess() kills a process outright Files, sockets, are closed, memory released, but buffers are not flushed

6 MEGADEATH Threads: pthreads Win32 Python
pthread_cancel() on cancellation points. Win32 TerminateThread() kills the thread dead. Python Threading.Thread has no kill() method Python resources (references) would not be cleaned up by a hard kill Pthread_cancel() could be used to implement a ‚soft‘ kill but is not available on all platforms. CPython thread switching is synchronized (via GIL) so sending exceptions to threads is technically possible CPython devs haven‘t drunk the Svali yet.

7 MEGADEATH Killing processes/threads:
If at all possible, it is messy (portability) C++ exception handling is usually not invoked Resources are released, but cleanup not executed Sockets are aborted, causing errors Locks are left un-released Buffers are left un-flushed Karma is left un-balanced

8 MEGADEATH Tasklets? Tasklet.kill() TaskletExit is BaseException
Sends a TaskletExit exception to the tasklet Immediatelly awakes the target Optional „pending“ delivery mode of exception TaskletExit is BaseException Not caught by regular exception filters which catch Exception objects Normally causes the exception to bubble to the top Finally clauses and context managers run as expected

9 Microlife Killing tasklets is synchronous
It is like sending a message to a blocking method Killing tasklets is not killing It is merely raising an exception It can even be caught, logged, handled, etc. Killing tasklet is not a system operation It invokes the language‘s native exception handling (unlike, e.g. C++)

10 Microlife Now we have an out-of-band way of sending messages to workers! Code written with proper try/finally scopes works as expected. Other apis and other exceptions can be used: Tasklet.kill(pending=True) # new feature Tasklet.throw(exc, val, tb, pending=False)

11 Microlife Examples:
def serve_forever(self, poll_interval=0.5):         """Handle one request at a time until shutdown.         Polls for shutdown every poll_interval seconds. Ignores         self.timeout. If you need to do periodic tasks, do them in         another thread.         """         self.__is_shut_down.clear()         try:             while not self.__shutdown_request:                 # XXX: Consider using another file descriptor or                 # connecting to the socket to wake this up instead of                 # polling. Polling reduces our responsiveness to a                 # shutdown request and wastes cpu at all other times.                 r, w, e =[self], [], [], poll_interval)                 if self in r:                     self._handle_request_noblock()         finally:             self.__shutdown_request = False             self.__is_shut_down.set()

12 Microlife Examples:
while True:             self.LogInfo("RunContactUpdates sleeping for", CONTACT_UPDATE_SLEEPTIME, "minutes")             blue.pyos.synchro.SleepWallclock(1000 * 60 * CONTACT_UPDATE_SLEEPTIME)             if not self.running:                 return

13 Dust UI UI code can be many tasklets doing things, e.g. Waiting for input. Complex UI state must be shut down e.g. When disconnection occurs UI tasklets register with the UI manager UI code carefully uses try:/finally: or context managers to release UI elements. UI manager can kill all registered tasklets, causing UI to be shut down gracefully.

14 Dust UI def UIDialogBoxWorker(): with UIManager.register_tasklet():
with UI.DialogueBox() as box: input = box.GetResult() # blocks here class UIManager(object): def OnClear(self): for worker in self.GetWorkers(): worker.kill()

15 Servitor Gated access to a service
def StartProcess(self): self.servitor = sake.servitor.DirectServitor() def ServitorCall(self, function, args): """ Wrap the call. This can involve a servitor, for example. The purpose of this is to allow Crust to cancel any calls that are in progress. """ # Use the DirectServitor. This causes TaskletExit calls to result # in a stacklesslib.errors.CancelledError to be raised. return, args) def Disconnect(self, *reasons): # We have decided to disconnect. Kill all calls currently in action self.servitor.kill_servitors(args=reasons) 

16 Servitor Clients is aware of CancelledError (or not):
def GetThrused(): svc = app.GetService('ThrusingService') try: return svc.DoTheThrus('I am the bethrused. Thrus me!') except stacklesslib.errors.CancelledError: # handle this error here: return None

17 Servitor Server wraps its api: class ThrusingService(service):
def StartService(self): self.servitor = servitor.SimpleServitor() def GetAPI(self): return servitor.WrapAPI(self) def CancelClients(self): self.servitor.cancel_clients() def DoTheThrus(self, subject): return, subject)

18 Softkill Tasklet kill is a soft kill
A gentle nudge of a rocking boat on a summer evening Requests a tasklet to politely stop what it is doing TaskletExit is a special exception that is silently ignored at the top level. Like a gentle rustle in the autumn leaves

19 Softkill What to be aware of:
Every stackless switching function can raise an exception. Running under watchdog, every instruction can raise an exception. (see: atomic) Must be aware of this if writing low-level stackless code, such as when using channels. stacklesslib.locks classes are exception-aware So are uthread.locks and others in EVE, I believe.

20 Softkill Best practices: Use context managers to tear down resources
Acquire locks, open files, etc. Know that blocking calls can raise exceptions But everyone knew that, right? Use „with stacklesslib.util.atomic():“ to guard critical stackless framework code. Because you just love to write your own synchronization primitives 

21 Do It! Never again write polling loops with exit request states
Grow a moustache or plant an herb garden. Go forth and procreate.

Download ppt "Why killing tasklets is good practice"

Similar presentations

Ads by Google