rread may return EAGAIN when socket configured blocking

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

There is ongoing work to support RDMA-based sockets in the JDK [1] (Java
Development Kit), which builds on top of rsocket and the underlying
platform support. The Java API allows configuration of both listening
and connecting sockets, as well as blocking and non-blocking. We've
encountered an issue where `rread`, on a socket configured to be
blocking, returns EAGAIN. This is an unexpected error code for such a
blocking socket and the Java implementation currently does not handle it
in a way that conforms to the higher-level Java API specification. We
either need to resolve the issue or workaround it somehow.

To demonstrate the issue I put together a native test ( includes no Java
 code ) [*]. The output os as follows:

$ ./testNonBlocking_raccept

listening on port 45361
connecting to 10.0.2.15:45361

accepted rs2: 8
reading ...
rread: Resource temporarily unavailable
rread returned: -1, errno: 11

This clearly demonstrates that EAGAIN is being returned from `rread`,
when the socket is configured blocking.

---

System configuration and details:
 $ cat /etc/os-release
 NAME="Ubuntu"
 VERSION="18.10 (Cosmic Cuttlefish)"
 ID=ubuntu
 ID_LIKE=debian
 PRETTY_NAME="Ubuntu 18.10"
 VERSION_ID="18.10"
 HOME_URL="https://www.ubuntu.com/";
 SUPPORT_URL="https://help.ubuntu.com/";
 BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/";

PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy";
 VERSION_CODENAME=cosmic
 UBUNTU_CODENAME=cosmic

 $ uname -a
Linux chhegar-VirtualBox 4.18.0-11-generic #12-Ubuntu SMP Tue Oct 23 19:22:37 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

 $ apt list | grep rdma
 librdmacm-dev/cosmic,now 19.0-1 amd64 [installed]
 librdmacm1/cosmic,now 19.0-1 amd64 [installed,automatic]
 rdma-core/cosmic,now 19.0-1 amd64 [installed]
 rdmacm-utils/cosmic,now 19.0-1 amd64 [installed]

 - No special hardware installed, using Soft-RoCE
 $ lsmod | grep rdma
 rdma_rxe              118784  0
 rpcrdma               221184  0
 sunrpc                364544  1 rpcrdma
 ip6_udp_tunnel         16384  1 rdma_rxe
 udp_tunnel             16384  1 rdma_rxe
 rdma_ucm               28672  0
 rdma_cm                61440  3 rpcrdma,ib_iser,rdma_ucm
 iw_cm                  45056  1 rdma_cm
 ib_cm                  53248  1 rdma_cm
 ib_uverbs              94208  1 rdma_ucm
ib_core 233472 8 rdma_cm,rdma_rxe,rpcrdma,iw_cm,ib_iser,rdma_ucm,ib_uverbs,ib_cm

 $ rxe_cfg status
   Name    Link  Driver  Speed  NMTU  IPv4_addr  RDEV  RMTU
   enp0s3  yes   e1000                           rxe0  1024  (3)

Regards,
-Chris.

[1] http://openjdk.java.net/jeps/337

[*]
// gcc testNonBlocking_raccept.c -lrdmacm -lpthread -o testNonBlocking_raccept

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <rdma/rsocket.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>

static const char* hostname = "10.0.2.15";  // << INSERT YOUR IP HERE
static int port;

void *connecting_side_function(void *ptr) {
    int rs, ret;
    struct sockaddr_in addr;

    rs = rsocket(AF_INET, SOCK_STREAM, 0);
    if (rs < 0)
        perror("rsocket connecting-side");

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = port;

    ret = inet_aton(hostname, &addr.sin_addr);
    if (ret < 0)
        perror("inet_aton");

    fprintf(stdout, "\nconnecting to %s:%d \n",
            inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
    ret = rconnect(rs, (struct sockaddr *)&addr, sizeof(struct sockaddr));
    if (ret < 0) {
        perror("rconnect");
        exit(3);
    }
    fprintf(stdout, "\nconnected");

    usleep(100000);  // just wait
}

int main() {
    int rs1, rs2, ret;
    pthread_t thread;
    char buffer[256];
    struct sockaddr_in addr, addr2;
    socklen_t addr_len = sizeof(addr);

    rs1 = rsocket(AF_INET, SOCK_STREAM, 0);
    if (rs1 < 0)
        perror("rsocket");

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(0);
    ret = rbind(rs1, (struct sockaddr *) &addr, addr_len);
    if (ret < 0)
        perror("rbind");

    ret = rlisten(rs1, 10);
    if (ret < 0)
        perror("rlisten");

    memset(&addr, 0, sizeof(addr));
    if (rgetsockname(rs1, (struct sockaddr *) &addr, &addr_len) < 0)
        perror("rgetsockname");
    port = addr.sin_port;
    fprintf(stdout, "\nlistening on port %d", ntohs(port));

    // Configure the listening socket to be non-blocking
    rfcntl(rs1, F_SETFL, (rfcntl(rs2, F_GETFL) | O_NONBLOCK));

    // Start the connecting thread
    pthread_create(&thread, NULL, connecting_side_function, (void*) NULL);

    while (1) {
        rs2 = raccept(rs1, (struct sockaddr *)&addr2, &addr_len);
        if (rs2 >= 0) {
           fprintf(stdout, "\naccepted rs2: %d ", rs2);
           break;
        } else if (rs2 < 0 && !(errno == EAGAIN || errno == EWOULDBLOCK)) {
            perror("raccept");
            exit(1);
        }
        usleep(50*100);
    }

    // Configure the accepted socket to be blocking
    rfcntl(rs1, F_SETFL, (rfcntl(rs2, F_GETFL) & ~O_NONBLOCK));

    //usleep(10*100);  // if you wait a little all is ok!!!

    fprintf(stdout, "\nreading ...");
    fflush(stdout);
    ret = rread(rs2, buffer, 255);
    if (ret < 0) {
        fprintf(stdout, "\nrread returned: %d, errno: %d ", ret, errno);
        perror("rread");
    } else {
        fprintf(stdout, "\nrread returned: %d ", ret);
    }
}



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux