예제 #1
0
    def execve(self, pid):
        enter = self.arg

        dbg.infom("!", "#R<re-execute#>: %s" % str(enter))
        fn = enter.args["filename"].path
        argv = enter.args["argv"]
        envp = enter.args["envp"]

        [ret, root, pwd, fds] = self.ret.aux

        # set sequence number as execve()'s sid
        self.seq = enter.sid & ((1 << 48) - 1) + 1

        # XXX
        # - setup fds
        self.proc = rerun.Ptrace([fn] + argv[1:], envp, kutil.get(pwd),
                                 kutil.get(root) if root.ino != 2 else None,
                                 self.uids)

        # enter/exit should be execve() too
        (r, p) = self.proc.load(True, None)
        (r, p) = self.proc.load(False, None)

        assert r.usage & EXIT and r.nr == syscall.NR_execve

        # virtualize pid
        self.pids[pid] = r.pid
        dbg.rerun("vpid:%s -> pid:%s (active)" % (pid, r.pid))

        # enable rerun module
        self.state = "active"
예제 #2
0
    def process_action(self):
        self.next = self.pick_action
        dbg.infom(
            '*', '%s:%s' % (prettify(self.action),
                            "same" if self.action.equiv() else "#R<changed#>"))

        # dbg.infom('*', '[%s]%s:%s' % (prettify(self.action.tic),
        #         prettify(self.action),
        #         "S" if self.action.equiv() else "#R<D#>"))

        # ipopov: conjecture:
        # The purpose of this if/elif/else chain is to prevent the redo
        # from continuing if any of the statements in the elif's return to
        # the effect that other nodes have been updated during this pass
        # through process_action(). Why do we care? Because this class is
        # implemented as a state machine, and processing maintains the
        # invariant that the action being redone now is the earliest one.
        # But connect() and prepare_redo() may affect the invariant.

        if (not self.action.cancel and self.action.equiv() and all([
                self.cur_state[n] >= self.action
                for n in self.action.outputs | set([self.action.actor])
        ])):
            dbg.info('skipping', self.action)
            for n in self.action.inputs:
                self.set_cs(n, max(self.cur_state[n], self.action))
            self.set_color(self.action, self.colors['skipped'])
        elif not self.action.connect():
            dbg.debug('retrying after connect')
        elif not self.prepare_redo():
            dbg.debug('retrying after prepare')
        elif self.action.cancel:
            if hasattr(self.action, 'cancel_hook'):
                self.action.cancel_hook()
            dbg.info('cancelled action', self.action)
            self.next = self.update_state
            self.set_color(self.action, self.colors['cancelled'])
        else:
            dbg.info('#G<redoing#> ', prettify(self.action))
            self.save_ckpts(self.action.outputs, self.action)
            try:
                self.action.redo()
            except mgrapi.ReschedulePendingException:
                dbg.info('rescheduling %s' % prettify(self.action))
                return
            else:
                self.next = self.update_state
                self.set_color(self.action, self.colors['redone'])
예제 #3
0
 def dump_graph(self):
     """Print, through dbg.infom(), the nodes and actions that this
 instance contains. (ipopov)"""
     for o in self.cur_state:
         dbg.infom('%s' % (o.__class__.__name__))
         for a in self.actions(o):
             dbg.infom(' -> %s' % (a.__class__.__name__))
             dbg.infom('    -> actor %s' % (a.actor.__class__.__name__))
예제 #4
0
파일: fsmgr.py 프로젝트: haowu4682/repair
    def rollback(self, c):
        assert (isinstance(c, FileCheckpoint))

        # XXX. hack to ignore /proc entries
        if any(c.d_pn.startswith(d) for d in ["/proc", "/dev"]):
            return

        cp_ino = None  # ino of the directory _entry_

        cpn = c.pn()
        if cpn:
            cp_ino = self._get_inode(cpn, self.name_in_dir)

        dev_pn = kutil.fsget(self.dev)
        dir_pn = kutil.iget(dev_pn, self.ino)

        cur_ino = self._get_inode(dir_pn, self.name_in_dir)

        if cp_ino == cur_ino:
            return

        if cur_ino is not None:
            # backup
            src = os.path.join(dir_pn, self.name_in_dir)
            dst = os.path.join(dev_pn, ".inodes", str(cur_ino))

            dbg.infom("!", "#R<rename#>: %s -> %s" % (src, dst))
            dbg.infom("readers %s" % str(self.readers))
            dbg.infom("writers %s" % str(self.writers))

            if not runopts.dryrun:
                os.rename(src, dst)

        if cp_ino is not None:
            src = kutil.iget(dev_pn, cp_ino)
            dst = os.path.join(dir_pn, self.name_in_dir)

            dbg.infom("!", "#R<link#>: %s -> %s" % (src, dst))

            if not runopts.dryrun:
                os.link(src, dst)

        kutil.dcache_flush()
예제 #5
0
파일: fsmgr.py 프로젝트: haowu4682/repair
    def rollback(self, c):
        assert (isinstance(c, FileCheckpoint))

        # XXX. hack to ignore /proc and /dev entries
        if any(c.d_pn.startswith(d) for d in ["/proc", "/dev"]):
            return None

        cpn = c.pn()

        try:
            dev_pn = kutil.fsget(self.dev)
            ino_pn = kutil.iget(dev_pn, self.ino)
        except kutil.MissingInode:
            if cpn is None:
                return

        dbg.infom("!", "#R<rollback#> %s(%s) -> %s" % (self.ino, ino_pn, cpn))
        dbg.infom("readers %s" % str(self.readers))
        dbg.infom("writers %s" % str(self.writers))

        if runopts.dryrun:
            return

        cstat = os.lstat(cpn) if cpn else None
        istat = os.lstat(ino_pn)

        if (cstat
                and stat.S_IFMT(istat.st_mode) != stat.S_IFMT(cstat.st_mode)):
            raise Exception('inode changed types', cpn, ino_pn, cstat, istat)

        if stat.S_ISREG(istat.st_mode):
            if cpn:
                with open(cpn, 'r') as f1:
                    f1data = f1.read()
            else:
                f1data = ''
            with open(ino_pn, 'r') as f2:
                f2data = f2.read()
            if f1data != f2data:
                with open(ino_pn, 'w') as f2:
                    f2.write(f1data)
        elif stat.S_ISLNK(istat.st_mode):
            pass  ## no way to change existing symlink
        elif stat.S_ISDIR(istat.st_mode):
            # XXX.
            pass
        else:
            raise Exception('cannot handle inode type',
                            stat.S_IFMT(istat.st_mode))
예제 #6
0
    def redo(self):
        """Execute another action of this action's actor. If the greedy
    heuristic matches the current action to the action just executed,
    we're fine. Otherwise, call parse_record() to create a new node in
    the action history graph.
    """

        dbg.syscall("redoing")
        rerun = self.actor.rerun

        if not rerun:
            dbg.syscall("no rerun instance bound to ProcSyscall %s;"
                        "returning prematurely" % self)
            return

        # following history while rerunning
        if rerun.is_following():
            (r, p) = rerun.next(True, self.actor.pid)
            if r == None:
                dbg.syscall('Aborting syscall; rerun returned no record')
                return
            assert r.usage & ENTER

            # special treatment of wait4
            # (see note in wait4.doc)
            # The following if statement seems pretty impenetrable. What I think it
            # does is the following. If a process under rerun tries to execute a
            # wait4, but that doesn't match up with the expected syscall from the
            # previous execution, call code.interact() and handle it manually.
            if (r.nr == syscall.NR_wait4
                    and self.argsnode.origdata.nr != syscall.NR_wait4):
                dbg.rerun('entering interactive')
                code.interact(local=locals())

                # wait4() again, at this time we should be able
                # to fetch child exit status
                (r, p) = rerun.next(False, self.actor.pid)
                assert r.usage & ENTER and r.nr == syscall.NR_wait4

                # this is a real system call we should execute
                # on this action node
                (r, p) = rerun.next(True, self.actor.pid)
                assert r.usage & ENTER

            # match up
            if (self.argsnode.origdata.nr == r.nr
                    and check_args(r, self.argsnode.origdata)):
                # update arguments
                self.argsnode.data = deepcopy(self.argsnode.origdata)
                self.argsnode.data.args = r.args
                self.argsnode.rerun = rerun

            # failed: need to explore/create new nodes/edges
            else:
                dbg.infom(
                    "!", "#R<mismatched#> syscalls: %s vs %s" %
                    (self.argsnode.origdata, r))
                assert self.argsnode.data == None
                ts = 0
                for a in rerun.actors:
                    t = max(a.actions)
                    if ts < t.tac:
                        ts = t.tac

                rerun.detach(r, ts)

                # Actually create a new node to correspond to what was just
                # executed.
                self.osloader.parse_record(r)

        # rerunning but creating new nodes/edges
        elif rerun.is_state("detached"):
            # if detached node
            if rerun.wait_r == self.argsnode.origdata:
                rerun.resume()
                #rerun.activate()

        # ipopov: ????
        if rerun.is_expanding():
            self.argsnode.data = self.argsnode.origdata
            self.argsnode.rerun = rerun