def run_process(self, analysis, action_name, message='__nomessagetoken__'):
        """Executes an process in the analysis with the given message.

        It also handles the start and stop signals in case an process_id
        is given.

        This method is similar to the method in databench.Analysis.
        """

        # detect process_id
        process_id = None
        if isinstance(message, dict) and '__process_id' in message:
            process_id = message['__process_id']
            del message['__process_id']

        if process_id:
            analysis.emit('__process', {'id': process_id, 'status': 'start'})

        fns = [
            functools.partial(class_fn, analysis)
            for class_fn in (analysis._action_handlers.get(action_name, []) +
                             analysis._action_handlers.get('*', []))
        ]
        if fns:
            args, kwargs = [], {}

            # Check whether this is a list (positional arguments)
            # or a dictionary (keyword arguments).
            if isinstance(message, list):
                args = message
            elif isinstance(message, dict):
                kwargs = message
            elif message == '__nomessagetoken__':
                pass
            else:
                args = [message]

            for fn in fns:
                log.debug('kernel calling {}'.format(fn))
                fn(*args, **kwargs)
        else:
            # default is to store action name and data as key and value
            # in analysis.data
            #
            # TODO(sven): deprecate this in favor of set_state() in Analysis
            # with new Datastore
            value = message if message != '__nomessagetoken__' else None
            if hasattr(analysis.data, 'set_state'):
                # TODO(sven): add deprecation warning here?
                analysis.data.set_state({action_name: value})
            else:
                # TODO(sven): add deprecation warning here?
                analysis.data[action_name] = value

        log.debug('kernel done {}'.format(action_name))

        if process_id:
            analysis.emit('__process', {'id': process_id, 'status': 'end'})

        if action_name == 'disconnected':
            log.debug('kernel {} shutting down'.format(analysis.id_))
            self.zmq_publish.close()

            self.zmq_stream_sub.close()
            self.zmq_sub.close()
            self.zmq_sub_ctx.destroy()