示例#1
0
def _test_mutex(mu, lock, unlock):
    # verify that g2 mu.lock() blocks until g1 does mu.unlock()
    getattr(mu, lock)()
    l = []
    done = chan()

    def _():
        getattr(mu, lock)()
        l.append('b')
        getattr(mu, unlock)()
        done.close()

    go(_)
    time.sleep(1 * dt)
    l.append('a')
    getattr(mu, unlock)()
    done.recv()
    assert l == ['a', 'b']

    # the same via with
    with mu:
        l = []
        done = chan()

        def _():
            with mu:
                l.append('d')
            done.close()

        go(_)
        time.sleep(1 * dt)
        l.append('c')
    done.recv()
    assert l == ['c', 'd']
示例#2
0
def main():
    ng = 100  # N(tasks) to spawn
    gstarted = chan()  # main <- g
    mainexit = chan()  # main -> all g

    # a task that wants to live longer than main
    def leaktask():
        gstarted.send(1)
        mainexit.recv()

        # normally when main thread exits, the whole process is terminated.
        # however if go spawns a thread with daemon=0, we are left here to continue.
        # make sure it is not the case
        time.sleep(3)
        print("leaked goroutine: process did not terminate", file=sys.stderr)
        sys.stderr.flush()
        time.sleep(1)
        os._exit(1)  # not sys.exit - that can be used only from main thread

    for i in range(ng):
        go(leaktask)

    # make sure all tasks are started
    for i in range(ng):
        gstarted.recv()

    # now we can exit
    mainexit.close()
    sys.exit(0)
示例#3
0
文件: __init__.py 项目: navytux/go123
def _vnet_accept(n, src, dst, netconn):
    with n._hostmu:
        host = n._hostmap.get(dst.host)
    if host is None:
        raise net.gaierror('%s: no such host' % dst.host)

    host._sockmu.acquire()

    if dst.port >= len(host._socketv):
        host._sockmu.release()
        raise ErrConnRefused

    sk = host._socketv[dst.port]
    if sk is None or sk._listener is None:
        host._sockmu.release()
        raise ErrConnRefused

    l = sk._listener
    host._sockmu.release()

    resp = chan()
    req = dialReq(src, netconn, resp)

    _, _rx = select(
        l._down.recv,  # 0
        (l._dialq.send, req),  # 1
    )
    if _ == 0:
        raise ErrConnRefused
    if _ == 1:
        return resp.recv()
示例#4
0
def test_waitgroup():
    wg = sync.WaitGroup()
    wg.add(2)

    ch = chan(3)

    def _():
        wg.wait()
        ch.send('a')

    for i in range(3):
        go(_)

    wg.done()
    assert len(ch) == 0
    time.sleep(0.1)
    assert len(ch) == 0
    wg.done()

    for i in range(3):
        assert ch.recv() == 'a'

    wg.add(1)
    go(_)
    time.sleep(0.1)
    assert len(ch) == 0
    wg.done()
    assert ch.recv() == 'a'

    with panics("sync: negative WaitGroup counter"):
        wg.done()
示例#5
0
def test_rwmutex():
    mu = sync.RWMutex()

    # Unlock  without lock -> panic
    # RUnlock without lock -> panic
    with panics("sync: Unlock of unlocked RWMutex"):
        mu.Unlock()
    with panics("sync: RUnlock of unlocked RWMutex"):
        mu.RUnlock()

    # Lock vs Lock; was also tested in test_rwmutex_basic
    mu.Lock()
    l = []
    done = chan()

    def _():
        mu.Lock()
        l.append('b')
        mu.Unlock()
        done.close()

    go(_)
    time.sleep(1 * dt)
    l.append('a')
    mu.Unlock()
    done.recv()
    assert l == ['a', 'b']
示例#6
0
文件: __init__.py 项目: navytux/go123
 def __init__(self, subnet, name):
     self._subnet = subnet
     self._name = name
     self._sockmu = threading.Lock()
     self._socketv = []
     self._down = chan()
     self._down_once = threading.Event()
     self._close_once = sync.Once()
示例#7
0
文件: __init__.py 项目: navytux/go123
 def __init__(self, network, registry):
     self._network = network
     self._registry = registry
     self._hostmu = threading.Lock()
     self._hostmap = {}
     self._nopenhosts = 0
     self._autoclose = False
     self._down = chan()
     self._down_once = threading.Event()
示例#8
0
文件: __init__.py 项目: navytux/go123
def accept(l):
    h = l._socket._host

    with errctx("accept %s %s" % (h.network(), l.addr())):
        while 1:
            _, _rx = select(
                l._down.recv,  # 0
                l._dialq.recv,  # 1
            )
            if _ == 0:
                l._excDown()
            if _ == 1:
                req = _rx

            with h._sockmu:
                sk = h._allocFreeSocket()

            ack = chan()
            req._resp.send(Accept(sk.addr(), ack))

            _, _rx = select(
                l._down.recv,  # 0
                ack.recv,  # 1
            )
            if _ == 0:

                def purgesk():
                    err = ack.recv()
                    if err is None:
                        try:
                            req._netsk.close()
                        except:
                            pass
                    with h._sockmu:
                        h._socketv[sk._port] = None

                go(purgesk)
                l._excDown()

            if _ == 1:
                err = _rx

            if err is not None:
                with h._sockmu:
                    h._socketv[sk._port] = None
                continue

            c = conn(sk, req._from, req._netsk)
            with h._sockmu:
                sk.conn = c

            return c
示例#9
0
def test_notify_reinstall():
    ch = chan(10, dtype=gos.Signal)
    def _():
        signal.Stop(ch)
    defer(_)

    for i in range(N):
        signal.Stop(ch)
        signal.Notify(ch, syscall.SIGUSR1)

    time.sleep(0.1*time.second)
    assert len(ch) == 0
    killme(syscall.SIGUSR1)
    time.sleep(0.1*time.second)
    assert len(ch) == 1
示例#10
0
def test_sema_wakeup_different_thread():
    sema = sync.Sema()
    sema.acquire()
    l = []
    done = chan()
    def _():
        time.sleep(1*dt)
        l.append('a')
        sema.release()
        done.close()
    go(_)
    sema.acquire()
    l.append('b')
    done.recv()
    assert l == ['a', 'b']
示例#11
0
def main():
    # build "all signals" list
    allsigv = []
    for attr in dir(syscall):
        if attr.startswith("SIG") and "_" not in attr:
            sig = getattr(syscall, attr)
            if sig not in allsigv: # avoid e.g. SIGCHLD/SIGCLD dups
                allsigv.append(sig)
    allsigv.sort(key=lambda sig: sig.signo)
    allsigv.remove(syscall.SIGKILL) # SIGKILL/SIGSTOP cannot be caught
    allsigv.remove(syscall.SIGSTOP)
    allsigv.remove(syscall.SIGBUS)  # AddressSanitizer crashes on SIGBUS/SIGFPE/SIGSEGV
    allsigv.remove(syscall.SIGFPE)
    allsigv.remove(syscall.SIGSEGV)

    # Notify() -> kill * -> should be notified
    ch = chan(10, dtype=gos.Signal)
    signal.Notify(ch) # all signals
    for sig in allsigv:
        emit("-> %d %s" % (sig.signo, sig))
        killme(sig)
        xsig = ch.recv()
        emit("<- %d %s" % (xsig.signo, xsig))
        if xsig != sig:
            raise AssertionError("got %s, expected %s" % (xsig, sig))
    emit("ok (notify)")

    # Ignore() -> kill * -> should not be notified
    emit()
    signal.Ignore() # all signals
    assert len(ch) == 0
    for sig in allsigv:
        emit("-> %d %s" % (sig.signo, sig))
        killme(sig)
        assert len(ch) == 0
    time.sleep(0.3)
    assert len(ch) == 0
    emit("ok (ignore)")

    # Reset() -> kill * should be handled by OS by default
    emit()
    signal.Reset() # all signals
    emit("terminating ...")
    killme(syscall.SIGTERM)
    raise AssertionError("not terminated")
示例#12
0
文件: __init__.py 项目: navytux/go123
 def __init__(self, sk, peerAddr, netsk):
     self._socket, self._peerAddr, self._netsk = sk, peerAddr, netsk
     self._down = chan()
     self._down_once = threading.Event()
     self._close_once = threading.Event()
示例#13
0
文件: __init__.py 项目: navytux/go123
 def __init__(self, sk):
     self._socket = sk
     self._dialq = chan()
     self._down = chan()
     self._down_once = threading.Event()
     self._close_once = threading.Event()
示例#14
0
def test_rwmutex_lock_vs_rlock(unlock_via_downgrade):
    mu = sync.RWMutex()

    # Lock vs RLock
    l = []  # accessed as R R R ... R  W  R R R ... R
    Nr1 = 10  # Nreaders queued before W
    Nr2 = 15  # Nreaders queued after  W
    mu.RLock()
    locked = chan(Nr1 + 1 * 3 + Nr2)  # main <- R|W: mu locked
    rcont = chan()  # main -> R: continue

    def R():  # readers
        mu.RLock()
        locked.send(('R', len(l)))
        rcont.recv()
        mu.RUnlock()

    for i in range(Nr1):
        go(R)

    # make sure all Nr1 readers entered mu.RLock
    for i in range(Nr1):
        assert locked.recv() == ('R', 0)

    # spawn W
    def W():  # 1 writer
        mu.Lock()
        time.sleep(
            Nr2 *
            dt)  # give R2 readers more chance to call mu.RLock and run first
        locked.send('W')
        l.append('a')
        if not unlock_via_downgrade:
            locked.send('_WUnlock')
            mu.Unlock()
        else:
            locked.send('_WUnlockToRLock')
            mu.UnlockToRLock()
            time.sleep(Nr2 * dt)
            locked.send('_WRUnlock')
            mu.RUnlock()

    go(W)

    # spawn more readers to verify that Lock has priority over RLock
    time.sleep(1 * dt)  # give W more chance to call mu.Lock first
    for i in range(Nr2):
        go(R)

    # release main rlock, make sure nor W nor more R are yet ready, and let all readers continue
    time.sleep((1 + 1) * dt)
    mu.RUnlock()
    time.sleep(1 * dt)
    for i in range(100):
        _, _rx = select(
            default,  # 0
            locked.recv,  # 1
        )
        assert _ == 0
    rcont.close()

    # W must get the lock first and all R2 readers only after it
    assert locked.recv() == 'W'
    if not unlock_via_downgrade:
        assert locked.recv() == '_WUnlock'
    else:
        assert locked.recv() == '_WUnlockToRLock'
    for i in range(Nr2):
        assert locked.recv() == ('R', 1)
    if unlock_via_downgrade:
        assert locked.recv() == '_WRUnlock'
示例#15
0
def test_signal():
    # Notify/Stop with wrong chan dtype -> panic
    _ = panics("pychan: channel type mismatch")
    with _:  signal.Notify(chan(2), syscall.SIGUSR1)
    with _:  signal.Stop  (chan(2))
    with _:  signal.Notify(chan(2, dtype='C.int'), syscall.SIGUSR1)
    with _:  signal.Stop  (chan(2, dtype='C.int'))

    # Notify/Ignore/Reset with wrong signal type
    _ = raises(TypeError)
    with _:  signal.Notify(chan(dtype=gos.Signal), None)
    with _:  signal.Ignore(None)
    with _:  signal.Reset(None)

    # subscribe ch1(USR1), ch12(USR1,USR2) and ch2(USR2)
    ch1  = chan(2, dtype=gos.Signal)
    ch12 = chan(2, dtype=gos.Signal)
    ch2  = chan(2, dtype=gos.Signal)
    signal.Notify(ch1,  syscall.SIGUSR1)
    signal.Notify(ch12, syscall.SIGUSR1, syscall.SIGUSR2)
    signal.Notify(ch2,                   syscall.SIGUSR2)
    def _():
        signal.Reset()
    defer(_)

    for i in range(N):
        # raise SIGUSR1 -> should be delivered to ch1 and ch12
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1 and len(ch12) == 1)
        sig1  = ch1.recv()
        sig12 = ch12.recv()
        assert sig1  == syscall.SIGUSR1
        assert sig12 == syscall.SIGUSR1

        # raise SIGUSR2 -> should be delivered to         ch12 and ch2
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR2)
        waitfor(lambda: len(ch12) == 1 and len(ch2) == 1)
        sig12 = ch12.recv()
        sig2  = ch2.recv()
        assert sig12 == syscall.SIGUSR2
        assert sig2  == syscall.SIGUSR2
        # if SIGUSR2 will be eventually delivered to ch1 - it will break
        # in SIGUSR1 check on next iteration.

    # Stop(ch2) -> signals should not be delivered to ch2 anymore
    signal.Stop(ch2)
    for i in range(N):
        # USR1 -> ch1, ch12
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1 and len(ch12) == 1)
        sig1  = ch1.recv()
        sig12 = ch12.recv()
        assert sig1  == syscall.SIGUSR1
        assert sig12 == syscall.SIGUSR1

        # USR2 -> ch12, !ch2
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR2)
        waitfor(lambda: len(ch12) == 1)
        sig12 = ch12.recv()
        assert sig12 == syscall.SIGUSR2
        # if SIGUSR2 will be eventually delivered to ch2 - it will break on
        # next iteration.

    # Ignore(USR1) -> ch1 should not be delivered to anymore, ch12 should be delivered only USR2
    signal.Ignore(syscall.SIGUSR1)
    for i in range(N):
        # USR1 -> ø
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR1)
        time.sleep(1E-6)

        # USR2 -> ch12
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR2)
        waitfor(lambda: len(ch12) == 1)
        sig12 = ch12.recv()
        assert sig12 == syscall.SIGUSR2
        # if SIGUSR1 or SIGUSR2 will be eventually delivered to ch1 or ch2 - it
        # will break on next iteration.

    # Notify after Ignore
    signal.Notify(ch1, syscall.SIGUSR1)
    for i in range(N):
        # USR1 -> ch1
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1)
        sig1 = ch1.recv()
        assert sig1 == syscall.SIGUSR1

        # USR2 -> ch12
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR2)
        waitfor(lambda: len(ch12) == 1)
        sig12 = ch12.recv()
        assert sig12 == syscall.SIGUSR2
示例#16
0
def test_stdlib_interop_KeyboardInterrupt():
    # KeyboardInterrupt is raised by default
    with raises(KeyboardInterrupt):
        killme(syscall.SIGINT)
        time.sleep(1)

    ch1 = chan(2, dtype=gos.Signal)
    ch2 = chan(2, dtype=gos.Signal)
    def _():
        signal.Reset(syscall.SIGINT)
    defer(_)

    # Notify disables raising KeyboardInterrupt by default on SIGINT
    signal.Notify(ch1, syscall.SIGINT)
    try:
        killme(syscall.SIGINT)
        waitfor(lambda: len(ch1) == 1)
        obj1 = ch1.recv()
        assert obj1 == syscall.SIGINT
        time.sleep(0.1) # just in case
    except KeyboardInterrupt:
        raise AssertionError("KeyboardInterrupt raised after signal.Notify +ch1")

    signal.Notify(ch2, syscall.SIGINT)
    try:
        killme(syscall.SIGINT)
        waitfor(lambda: len(ch1) == 1 and len(ch2) == 1)
        obj1 = ch1.recv()
        obj2 = ch2.recv()
        assert obj1 == syscall.SIGINT
        assert obj2 == syscall.SIGINT
        time.sleep(0.1) # just in case
    except KeyboardInterrupt:
        raise AssertionError("KeyboardInterrupt raised after signal.Notify +ch1 +ch2")

    # last Stop should reenable raising KeyboardInterrupt by default on SIGINT
    signal.Stop(ch1)
    try:
        killme(syscall.SIGINT)
        waitfor(lambda: len(ch2) == 1)
        obj2 = ch2.recv()
        assert obj2 == syscall.SIGINT
        time.sleep(0.1) # just in case
        assert len(ch1) == 0
    except KeyboardInterrupt:
        raise AssertionError("KeyboardInterrupt raised after signal.Notify +ch1 +ch2 -ch1")

    signal.Stop(ch2)
    with raises(KeyboardInterrupt):
        killme(syscall.SIGINT)
        time.sleep(1)
    time.sleep(0.1) # just in case
    assert len(ch1) == 0
    assert len(ch2) == 0

    # Ignore disables raising KeyboardInterrupt by default on SIGINT
    signal.Ignore(syscall.SIGINT)
    try:
        killme(syscall.SIGINT)
        time.sleep(0.1)
        assert len(ch1) == 0
        assert len(ch2) == 0
    except KeyboardInterrupt:
        raise AssertionError("KeyboardInterrupt raised after signal.Ignore")

    # Reset restores original behaviour
    signal.Reset(syscall.SIGINT)
    with raises(KeyboardInterrupt):
        killme(syscall.SIGINT)
        time.sleep(1)
    time.sleep(0.1) # just in case
    assert len(ch1) == 0
    assert len(ch2) == 0
示例#17
0
def test_stdlib_interop():
    import signal as pysig

    ch1 = chan(2, dtype=object) # NOTE not gos.Signal nor 'C.os::Signal'
    def _(signo, frame):
        ch1.send("USR1")
    pysig.signal(pysig.SIGUSR1, _)
    def _():
        pysig.signal(pysig.SIGUSR1, pysig.SIG_IGN)
    defer(_)

    # verify that plain pysig delivery works
    for i in range(N):
        assert len(ch1) == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1)
        obj1 = ch1.recv()
        assert obj1 == "USR1"

    # verify that combined pysig + golang.os.signal delivery works
    ch2 = chan(2, dtype=gos.Signal)
    signal.Notify(ch2, syscall.SIGUSR1)
    def _():
        signal.Stop(ch2)
    defer(_)

    for i in range(N):
        assert len(ch1) == 0
        assert len(ch2) == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1 and len(ch2) == 1)
        obj1 = ch1.recv()
        sig2 = ch2.recv()
        assert obj1 == "USR1"
        assert sig2 == syscall.SIGUSR1

    # Ignore stops delivery to both pysig and golang.os.signal
    signal.Ignore(syscall.SIGUSR1)
    for i in range(N):
        assert len(ch1) == 0
        assert len(ch2) == 0
        killme(syscall.SIGUSR1)
        time.sleep(1E-6)
    time.sleep(0.1) # just in case
    assert len(ch1) == 0
    assert len(ch2) == 0

    # after Reset pysig delivery is restored even after Ignore
    signal.Reset(syscall.SIGUSR1)
    for i in range(N):
        assert len(ch1) == 0
        assert len(ch2) == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1)
        assert len(ch2) == 0
        obj1 = ch1.recv()
        assert obj1 == "USR1"

    # Reset stops delivery to golang.os.signal and restores pysig delivery
    signal.Notify(ch2, syscall.SIGUSR1)
    signal.Reset(syscall.SIGUSR1)
    for i in range(N):
        assert len(ch1) == 0
        assert len(ch2) == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1)
        assert len(ch2) == 0
        obj1 = ch1.recv()
        assert obj1 == "USR1"