Ejemplo n.º 1
0
ssize_t udp_recvl_(struct msock_vfs *mvfs, struct ipaddr *addr,
      struct iolist *first, struct iolist *last, int64_t deadline) {
    struct udp_sock *obj = dill_cont(mvfs, struct udp_sock, mvfs);
    struct msghdr hdr;
    memset(&hdr, 0, sizeof(hdr));
    hdr.msg_name = (void*)addr;
    hdr.msg_namelen = sizeof(struct ipaddr);
    /* Make a local iovec array. */
    /* TODO: This is dangerous, it may cause stack overflow.
       There should probably be a on-heap per-socket buffer for that. */
    size_t niov;
    int rc = iol_check(first, last, &niov, NULL);
    if(dill_slow(rc < 0)) return -1;
    struct iovec iov[niov];
    iol_toiov(first, iov);
    hdr.msg_iov = (struct iovec*)iov;
    hdr.msg_iovlen = niov;
    while(1) {
        ssize_t sz = recvmsg(obj->fd, &hdr, 0);
        if(sz >= 0) return sz;
        if(errno != EAGAIN && errno != EWOULDBLOCK) return -1;
        rc = fdin(obj->fd, deadline);
        if(dill_slow(rc < 0)) return -1;
    }
}
int dsrecv(int s, void *buf, size_t *len, int64_t deadline) {
    size_t received = 0;
    while(1) {
        ssize_t sz = recv(s, ((char*)buf) + received, *len - received, 0);
        if(dill_slow(sz == 0)) {
            *len = received;
            errno = ECONNRESET;
            return -1;
        }
        if(sz < 0) {
            if(dill_slow(errno != EWOULDBLOCK && errno != EAGAIN)) {
                *len = received;
                return -1;
            }
        }
        else {
            received += sz;
            if(received >= *len)
                return 0;
        }
        int rc = fdin(s, deadline);
        if(dill_slow(rc < 0)) {
            *len = received;
            return -1;
        }
    }
}
int dsaccept(int s, struct sockaddr *addr, socklen_t *addrlen,
      int64_t deadline) {
    int as;
    while(1) {
        /* Try to accept new connection synchronously. */
        as = accept(s, addr, addrlen);
        if(dill_fast(as >= 0))
            break;
        if(dill_slow(errno != EAGAIN && errno != EWOULDBLOCK)) return -1;
        /* Operation is in progress. Wait till new connection is available. */
        int rc = fdin(s, deadline);
        if(dill_slow(rc < 0)) return -1;
    }
    int rc = dsunblock(as);
    dill_assert(rc == 0);
    return as;
}
Ejemplo n.º 4
0
int main() {
    /* Pipe to check whether child have failed. */
    int fds[2];
    int rc = pipe(fds);
    errno_assert(rc == 0);
    /* Start second coroutine before forking. */
    int h = go(worker());
    errno_assert(h >= 0);
    /* Fork. */
    h = proc(child(fds[1]));
    errno_assert(h >= 0);
    close(fds[1]);
    /* Parent waits for the child. */
    rc = fdin(fds[0], -1);
    errno_assert(rc == 0);

    return 0;
}
Ejemplo n.º 5
0
int main() {
    int rc;

    /* Check invalid fd. */
    rc = fdin(33, -1);
    assert(rc == -1 && errno == EBADF);
    rc = fdout(33, -1);
    assert(rc == -1 && errno == EBADF);

    /* Create a pair of file deshndliptors for testing. */
    int fds[2];
    rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
    errno_assert(rc == 0);

    /* Check for in & out. */
    rc = fdout(fds[0], 0);
    errno_assert(rc == 0);
    rc = fdin(fds[0], 0);
    assert(rc == -1 && errno == ETIMEDOUT);

    /* Check with infinite timeout. */
    rc = fdout(fds[0], -1);
    errno_assert(rc == 0);

    /* Check with the timeout that doesn't expire. */
    rc = fdout(fds[0], now() + 100);
    errno_assert(rc == 0);

    /* Check with the timeout that does expire. */
    int64_t deadline = now() + 100;
    rc = fdin(fds[0], deadline);
    assert(rc == -1 && errno == ETIMEDOUT);
    int64_t diff = now() - deadline;
    time_assert(diff, 0);

    /* Check cancelation. */
    int hndl1 = go(cancel(fds[0]));
    errno_assert(hndl1 >= 0);
    rc = hclose(hndl1);
    errno_assert(rc == 0);

    /* Check for in. */
    ssize_t sz = send(fds[1], "A", 1, 0);
    errno_assert(sz == 1);
    rc = fdin(fds[0], -1);
    errno_assert(rc == 0);
    char c;
    sz = recv(fds[0], &c, 1, 0);
    errno_assert(sz == 1);

    /* Two interleaved deadlines. */
    int64_t start = now();
    int hndl2 = go(trigger(fds[0], start + 50));
    errno_assert(hndl2 >= 0);
    rc = fdin(fds[1], start + 90);
    errno_assert(rc == 0);
    diff = now() - start;
    time_assert(diff, 50);
    rc = hclose(hndl2);
    errno_assert(rc == 0);

    /* Check whether closing the connection is reported. */
    ssize_t nbytes = send(fds[1], "ABC", 3, 0);
    errno_assert(nbytes == 3);
    rc = fdclean(fds[1]);
    errno_assert(rc == 0);
    rc = close(fds[1]);
    errno_assert(rc == 0);
    rc = msleep(now() + 50);
    errno_assert(rc == 0);
    rc = fdin(fds[0], -1);
    errno_assert(rc == 0);
    rc = fdout(fds[0], -1);
    errno_assert(rc == 0);
    char buf[10];
    nbytes = recv(fds[0], buf, sizeof(buf), 0);
    assert(nbytes == 3);
    rc = fdin(fds[0], -1);
    errno_assert(rc == 0);
    nbytes = recv(fds[0], buf, sizeof(buf), 0);
    assert(nbytes == 0 || (nbytes == -1 && errno == ECONNRESET));
    rc = fdclean(fds[0]);
    errno_assert(rc == 0);
    rc = close(fds[0]);
    errno_assert(rc == 0);

    /* Test whether fd is removed from the pollset after fdin/fdout times
       out. */
    int pp[2];
    rc = pipe(pp);
    assert(rc == 0);
    rc = fdin(pp[0], now() + 10);
    assert(rc == -1 && errno == ETIMEDOUT);
    nbytes = write(pp[1], "ABC", 3);
    assert(nbytes == 3);
    rc = msleep(now() + 100);
    assert(rc == 0);
    rc = fdclean(pp[0]);
    errno_assert(rc == 0);
    rc = fdclean(pp[1]);
    errno_assert(rc == 0);
    rc = close(pp[0]);
    assert(rc == 0);
    rc = close(pp[1]);
    assert(rc == 0);

    return 0;
}
Ejemplo n.º 6
0
coroutine void cancel(int fd) {
    int rc = fdin(fd, -1);
    assert(rc == -1 && errno == ECANCELED);
    rc = fdin(fd, -1);
    assert(rc == -1 && errno == ECANCELED);
}