Beispiel #1
0
 def wrapped(*args, **kwds):
     if not parallel_safe and session.checkParallel():
         raise UsageError('the %s command cannot be used with "execute now"'
                          % func.__name__)
     try:
         try:
             # try executing the original function with the given arguments
             return func(*args, **kwds)
         except TypeError:
             # find out if the call itself caused this error, which means
             # that wrong arguments were given to the command
             traceback = sys.exc_info()[2]
             # find last call frame
             while traceback.tb_next:
                 traceback = traceback.tb_next
             if traceback.tb_frame.f_code is wrapped.__code__:
                 session.log.error('Invalid arguments for %s()',
                                   func.__name__)
                 help(func)
             raise
         except UsageError:
             # for usage errors, print the error and the help for the
             # command
             help(func)
             raise
     except RERAISE_EXCEPTIONS:
         # don't handle these, they should lead to an unconditional abort
         raise
     except Exception:
         # all others we'll handle and continue, if wanted
         if hasattr(session.experiment, 'errorbehavior') and \
            session.experiment.errorbehavior == 'report':
             session.scriptEvent('exception', sys.exc_info())
         else:
             raise
Beispiel #2
0
    def update(self, text, reason, controller, user):
        """Update the code with a new script.

        This method is called from a different thread than execute(),
        so we must unset the _run flag before doing anything to
        self.curblock, self.code or self.blocks.
        """
        if not self.blocks:
            raise ScriptError('cannot update single-line script')
        text = fixupScript(text)
        newcode, newblocks = splitBlocks(text)
        # stop execution after the current block
        self._run.clear()
        curblock = self.curblock  # this may be off by one
        try:
            # make sure that everything that has already been executed matches
            if curblock >= len(newblocks):
                # insufficient number of new blocks
                raise ScriptError('new script too short')
            # compare all executed blocks
            for i in range(curblock + 1):
                if not self._compare(self.blocks[i], newblocks[i]):
                    raise ScriptError('new script differs in already executed '
                                      'part of the code')
            # everything is ok, replace the script and the remaining blocks
            self.text = text
            session.scriptEvent('update', (self.name, self.text))
            # also set the updating user as the new user of the script
            self.user = user
            if session._experiment and session.mode == MASTER:
                scr = list(session.experiment.scripts)  # convert readonly list
                scr[self._exp_script_index] = self.text
                session.experiment.scripts = scr
            updateLinecache('<script>', text)
            self.code, self.blocks = newcode, newblocks
            self.resetSimstate()
            # let the client know of the update
            controller.eventfunc('processing', self.serialize())
            updatemsg = 'UPDATE (%s)' % reason if reason else 'UPDATE'
            session.log.log(INPUT, formatScript(self, updatemsg))
        finally:
            # let the script continue execution in any case
            self._run.set()
Beispiel #3
0
 def execute(self, controller):
     """Execute the script in the given namespace, using "controller"
     to execute individual blocks.
     """
     session.scriptEvent('start', (self.name, self.text))
     session.countloop_request = None  # reset any pause flag from before
     # this is to allow the traceback module to report the script's
     # source code correctly
     updateLinecache('<script>', self.text)
     # note: checking session._experiment since using session.experiment
     # would try to create the device, which means you can't execute any
     # command when the experiment fails
     if session._experiment and session.mode == MASTER:
         session.experiment.scripts += [self.text]
         self._exp_script_index = len(session.experiment.scripts) - 1
     if self.name:
         session.elogEvent('scriptbegin', self.name)
         session.beginActionScope(path.basename(self.name))
     # notify clients of "input"
     session.log.log(INPUT, formatScript(self))
     try:
         while self.curblock < len(self.code) - 1:
             self._run.wait()
             self.curblock += 1
             self.blockStart = time.time()
             self.emitETA(controller)
             controller.start_exec(self.code[self.curblock],
                                   controller.namespace, None,
                                   self.settrace)
     finally:
         if self.name:
             session.endActionScope()
         if session._experiment and session.mode == MASTER:
             session.experiment.scripts = session.experiment.scripts[:-1]
         if self.name:
             session.elogEvent('scriptend', self.name)
Beispiel #4
0
 def my_runcode(self, codeobj, source=None):
     """Mostly copied from code.InteractiveInterpreter, but added better
     exception handling.
     """
     session.scriptEvent('start', ('', source))
     try:
         exec_(codeobj, self.globals)
     except NicosInteractiveStop:
         pass
     except KeyboardInterrupt:
         # "immediate stop" chosen
         session.immediateStop()
     except Exception:
         session.scriptEvent('exception', sys.exc_info())
     if hasattr(code, 'softspace') and code.softspace(sys.stdout, 0):
         print()
     session.scriptEvent('finish', None)
Beispiel #5
0
    def script_thread_entry(self):
        """The script execution thread entry point.  This thread executes setup
        code, then waits for scripts on self.queue.  The script is then
        executed in the context of self.namespace, using the controller (self)
        to watch execution.
        """
        self.log.debug('script_thread (re)started')
        session.script_thread_id = current_thread().ident
        try:
            self.namespace['NicosSetup'] = self._setup
            # and put it in the queue as the first request
            request = ScriptRequest('NicosSetup()',
                                    'setting up NICOS',
                                    system_user,
                                    quiet=True,
                                    format='py')
            self.new_request(request, notify=False)

            while 1:
                # get a script (or other request) from the queue
                request = self.queue.get()
                self.thread_data.user = request.user

                if isinstance(request, EmergencyStopRequest):
                    self.log.info('executing estop request from %s',
                                  request.user.name)
                    self.execute_estop(request.user.name)
                    continue
                elif not isinstance(request, ScriptRequest):
                    self.log.error('unknown request: %s', request)
                    continue
                self.log.info('processing script %s by %s', request.reqid,
                              request.user.name)
                self.reqid_work = request.reqid
                if session.cache and self.autosim:
                    self.simulate_request(request, quiet=True)
                    request.setSimstate('running')
                # notify clients that we're processing this request now
                self.eventfunc('processing', request.serialize())
                # parse the script and split it into blocks
                try:
                    self.current_script = request
                    self.current_script.parse()
                except Exception:
                    session.log.log(INPUT, formatScript(request))
                    session.logUnhandledException(cut_frames=1)
                    continue
                try:
                    self.current_script.execute(self)
                except ControlStop as err:
                    if err.args[0] == 'emergency stop':
                        # block all pending requests (should have been done
                        # already, but to be on the safe side do it here again)
                        self.block_all_requests()
                        self.execute_estop(err.args[2])
                    else:
                        # in this case, we have already blocked all scripts
                        # queued before the "stop" command was given; scripts
                        # that are queued after that should be executed, so
                        # we don't block requests here
                        session.log.info('Script stopped by %s', err.args[2])
                except BdbQuit as err:  # pylint: disable=bad-except-order
                    session.log.error('Script stopped through debugger')
                except Exception as err:  # pylint: disable=bad-except-order
                    # the topmost two frames are still in the
                    # daemon, so don't display them to the user
                    # perhaps also send an error notification
                    try:
                        session.scriptEvent('exception', sys.exc_info())
                    except Exception:
                        # last resort: do not exit script thread even if we
                        # can't handle this exception
                        pass
                if self.debugger:
                    self.debug_end(tracing=False)
                session.clearActions()
                session.scriptEvent('finish', None)
        except Exception:
            self.log.exception('unhandled exception in script thread')
            session.log.error('internal error in NICOS daemon, please restart')
        finally:
            self.thread = None