Exemplo n.º 1
0
 def signal(self, pid, sig):
     flags = self.allflags[pid]
     if sig == 'SIGTRAP':
         if flags.has_key('exectrappending'):
             # assume first SIGTRAP following an exec is due to the
             # exec (FIX: not strictly true?)
             del flags['exectrappending']
             return ('SIG_0',)
         # XXX: merge these?
         if flags.has_key('skiptrap'):
             del flags['skiptrap']
             return ('SIG_0',)
     elif sig == 'SIGCHLD' and flags.has_key('deathnotice'):
         # FIX: This is somewhat bogus.  For starters, don't do this if
         # parent or child has exec'ed since clone
         # FIX: this deathnotice queueing is probably bogus, too
         dpid, dsignal = flags['deathnotice'].pop(0)
         #if self.allflags.has_key(dpid): # ???
         #    del self.allflags[dpid]     # ???
         if not flags['deathnotice']:
             del flags['deathnotice']
         return (signalmap.lookup_name(dsignal),)
     elif sig == 'SIGSTOP' and flags.has_key('skipstop'):
         # in 2.4, there's a gratuitous SIGSTOP right after fork/etc
         del flags['skipstop']
         return ('SIG_0',)
Exemplo n.º 2
0
def trace_signal(pid, flags, tricklist, sig):
    if not _signal_weedout_mask[sig]:
        return sig

    signalname = signalmap.lookup_name(sig)

    # innermost trick gets first shot at the signal
    tricklist = tricklist[:]
    tricklist.reverse()

    for trick, callmask, signalmask in tricklist:
        if (not signalmask or signalmask.has_key(signalname)) and trick.is_enabled(pid):
            r = trick.signal(pid, signalname)
            # r is None or (signal, )
            if r != None:
                assert len(r) == 1, "signal must return None or a 1-tuple"
                signalname = r[0]
                assert isinstance(signalname, types.StringType) and (
                    0 <= signalmap.lookup_number(signalname) < signal.NSIG
                ), ("bad signal %s; must use signal name" % signalname)
                if signalname == "SIG_0":
                    break
                    # XXX: perhaps we ought to also ignore signals that the
                    # process is ignoring ??

    return signalmap.lookup_number(signalname)
Exemplo n.º 3
0
 def callafter(self, pid, call, result, state):
     if call == 'rt_sigaction' or call == 'sigaction' or call == 'signal':
         if state != None and not (-1024 < result < 0):
             sig = state[0]
             f = self.allflags[pid]
             handler = state[1]
             if sig == signal.SIGCHLD:
                 sa_flags = ptrace.peekdata(pid, handler + 4)
                 f['SA_NOCLDSTOP'] = sa_flags & 0x1 # SA_NOCLDSTOP
             else:
                 if call != 'signal':
                     handler = ptrace.peekdata(pid, handler)
                 f[signalmap.lookup_name(sig)] = handler
     elif call == 'wait4' or call == 'waitpid':
         f = self.allflags[pid]
         if f.has_key('waitresult'):
             wpid, statusptr, status = f['waitresult']
             del f['waitresult']
             del f['waiting']
             if statusptr != 0:
                 try:
                     ptrace.pokedata(pid, statusptr, status)
                 except OSError, e:
                     if e.errno != errno.ESRCH:
                         # FIX
                         assert 0, "wait status pointer bad? (%s)" % e
                     else:
                         print 'waiter dead or not stopped' # XXX
             return wpid
         # XXX: is this actually correct and useful?
         if result == -errno_internal.ERESTARTNOHAND: # like pause
             return -errno_internal.ERESTARTSYS # like wait
Exemplo n.º 4
0
def trace_exit(pid, flags, tricklist, exitstatus, termsig):
    signalname = None
    if termsig:
        signalname = signalmap.lookup_name(termsig)

    for trick, callmask, signalmask in tricklist:
        if trick.is_enabled(pid): trick.exit(pid, exitstatus, signalname)
Exemplo n.º 5
0
def trace_signal(pid, flags, tricklist, sig):
    if not _signal_weedout_mask[sig]:
        return sig

    signalname = signalmap.lookup_name(sig)

    # innermost trick gets first shot at the signal
    tricklist = tricklist[:]
    tricklist.reverse()

    for trick, callmask, signalmask in tricklist:
        if (not signalmask or signalmask.has_key(signalname))\
                                         and trick.is_enabled(pid):
            r = trick.signal(pid, signalname)
            # r is None or (signal, )
            if r != None:
                assert len(r) == 1, "signal must return None or a 1-tuple"
                signalname = r[0]
                assert (isinstance(signalname, types.StringType)
                 and (0 <= signalmap.lookup_number(signalname)
                      < signal.NSIG)), \
                       "bad signal %s; must use signal name" % signalname
                if signalname == 'SIG_0':
                    break
                # XXX: perhaps we ought to also ignore signals that the
                # process is ignoring ??

    return signalmap.lookup_number(signalname)
Exemplo n.º 6
0
def trace_exit(pid, flags, tricklist, exitstatus, termsig):
    signalname = None
    if termsig:
        signalname = signalmap.lookup_name(termsig)

    for trick, callmask, signalmask in tricklist:
        if trick.is_enabled(pid):
            trick.exit(pid, exitstatus, signalname)
Exemplo n.º 7
0
def handle_sf_signal(signo, frame, tricks):
    """Send a signal received by sf itself to the interested tricks."""

    # discard frame -- it's not part of the interface because this may be
    # reimplemented in another language

    signal = signalmap.lookup_name(signo)
    for trick in tricks:
        assert not trick.tricksignalmask \
               or trick.tricksignalmask().has_key(signal)
        trick.tricksignal(signal)
Exemplo n.º 8
0
def handle_sf_signal(signo, frame, tricks):
    """Send a signal received by sf itself to the interested tricks."""

    # discard frame -- it's not part of the interface because this may be
    # reimplemented in another language

    signal = signalmap.lookup_name(signo)
    for trick in tricks:
        assert not trick.tricksignalmask \
               or trick.tricksignalmask().has_key(signal)
        trick.tricksignal(signal)
Exemplo n.º 9
0
            if waitchannelhack:
                callstop = _subterfugue.atcallstop(wpid, stopsig)
            else:
                callstop = stopsig == signal.SIGTRAP | 0x80

            if not callstop:
                sig = trace_signal(wpid, flags, tricklist, stopsig)
                if (sig == signal.SIGSTOP or sig == signal.SIGTSTP
                    or sig == signal.SIGTTIN or sig == signal.SIGTTOU):
                    # FIX: more needed for ~SIGSTOP case
                    # ~SIGSTOP: if handler, pass like any other signal
                    # ~SIGSTOP: if IGN or DEF & orphaned pgrp, ignore
                    # all: stop
                    # all: if parent's SIGCHLD has !SA_NOCLDSTOP, notify
                    if sig != signal.SIGSTOP:
                        signame = signalmap.lookup_name(sig)
                        handler = flags.get(signame, signal.SIG_DFL)
                        if handler == signal.SIG_DFL:
                            pass        # FIX: handle orphaned pgrp
                        elif handler == signal.SIG_IGN:
                            ptrace.syscall(wpid, 0)
                            continue
                        else:
                            # XXX: it would seem that we could get a duplicate
                            # signal here, since the kernel will report this
                            # twice (?), but this doesn't seem to be happening
                            # (maybe because the signals merge?)
                            ptrace.syscall(wpid, sig)
                            continue

                    if flags.has_key('status'):
Exemplo n.º 10
0
            if waitchannelhack:
                callstop = _subterfugue.atcallstop(wpid, stopsig)
            else:
                callstop = stopsig == signal.SIGTRAP | 0x80

            if not callstop:
                sig = trace_signal(wpid, flags, tricklist, stopsig)
                if (sig == signal.SIGSTOP or sig == signal.SIGTSTP
                        or sig == signal.SIGTTIN or sig == signal.SIGTTOU):
                    # FIX: more needed for ~SIGSTOP case
                    # ~SIGSTOP: if handler, pass like any other signal
                    # ~SIGSTOP: if IGN or DEF & orphaned pgrp, ignore
                    # all: stop
                    # all: if parent's SIGCHLD has !SA_NOCLDSTOP, notify
                    if sig != signal.SIGSTOP:
                        signame = signalmap.lookup_name(sig)
                        handler = flags.get(signame, signal.SIG_DFL)
                        if handler == signal.SIG_DFL:
                            pass  # FIX: handle orphaned pgrp
                        elif handler == signal.SIG_IGN:
                            ptrace.syscall(wpid, 0)
                            continue
                        else:
                            # XXX: it would seem that we could get a duplicate
                            # signal here, since the kernel will report this
                            # twice (?), but this doesn't seem to be happening
                            # (maybe because the signals merge?)
                            ptrace.syscall(wpid, sig)
                            continue

                    if flags.has_key('status'):