/* waiting on non-existing handle that is in valid range. */ for (unsignedint i = first_free_handle_index; i < MAX_USER_HANDLES; i++) {
rc = wait(handle_base + i, &event, timeout);
EXPECT_EQ(ERR_NOT_FOUND, rc, "wait on invalid handle");
}
}
/* *Closehandleunittest
*/
TEST(IPC_LOCAL, DISABLED_WITH_COVERAGE(close_handle_negative)) { int rc;
/* set cookie for non-existing handle that is in valid range. */ for (unsignedint i = first_free_handle_index; i < MAX_USER_HANDLES; i++) {
rc = set_cookie(handle_base + i, (void*)0x3BEEF);
EXPECT_EQ(ERR_NOT_FOUND, rc, "set cookie for invalid handle");
}
}
/* *Duplicatehandleunittest
*/
TEST(IPC_LOCAL, DISABLED_WITH_COVERAGE(dup_negative)) { int rc;
/* create port with zero buffers */
sprintf(path, "%s.port", SRV_PATH_BASE);
rc = port_create(path, 0, 64, 0);
EXPECT_EQ(ERR_INVALID_ARGS, rc, "no buffers");
/* create port with zero buffer size */
sprintf(path, "%s.port", SRV_PATH_BASE);
rc = port_create(path, 2, 0, 0);
EXPECT_EQ(ERR_INVALID_ARGS, rc, "zero buf size");
/* create port with large number of buffers */
sprintf(path, "%s.port", SRV_PATH_BASE);
rc = port_create(path, MAX_PORT_BUF_NUM * 100, 64, 0);
EXPECT_EQ(ERR_INVALID_ARGS, rc, "large buf num");
/* create port with large buffer size */
sprintf(path, "%s.port", SRV_PATH_BASE);
rc = port_create(path, 2, MAX_PORT_BUF_SIZE * 100, 0);
EXPECT_EQ(ERR_INVALID_ARGS, rc, "large buf size");
/* create port with path oversized name */ int len = sprintf(path, "%s.port", SRV_PATH_BASE); for (size_t i = len; i < sizeof(path); i++)
path[i] = 'a';
path[sizeof(path) - 1] = '\0';
rc = port_create(path, 2, MAX_PORT_BUF_SIZE, 0);
EXPECT_EQ(ERR_INVALID_ARGS, rc, "path is too long");
rc = close((handle_t)rc);
EXPECT_EQ(ERR_BAD_HANDLE, rc, "close port");
}
/* create maximum number of ports */ for (i = first_free_handle_index; i < MAX_USER_HANDLES - 1; i++) {
sprintf(path, "%s.port.%s%d", SRV_PATH_BASE, "test", i);
rc = port_create(path, 2, MAX_PORT_BUF_SIZE, 0);
EXPECT_GT_ZERO(rc, "create ports");
ports[i] = (handle_t)rc;
/* create a new port that collide with an existing port */
rc = port_create(path, 2, MAX_PORT_BUF_SIZE, 0);
EXPECT_EQ(ERR_ALREADY_EXISTS, rc, "create existing port");
}
/* create one more that should succeed */
sprintf(path, "%s.port.%s%d", SRV_PATH_BASE, "test", i);
rc = port_create(path, 2, MAX_PORT_BUF_SIZE, 0);
EXPECT_GT_ZERO(rc, "create ports");
ports[i] = (handle_t)rc;
/* but creating colliding port should fail with different errorcodebecauseweactuallyexceededmaxnumberof
handles instead of colliding with an existing path */
rc = port_create(path, 2, MAX_PORT_BUF_SIZE, 0);
EXPECT_EQ(ERR_NO_RESOURCES, rc, "create existing port");
/* close them all */ for (i = first_free_handle_index; i < MAX_USER_HANDLES; i++) { /* close a valid port */
rc = close(ports[i]);
EXPECT_EQ(NO_ERROR, rc, "closing port");
/* close previously closed port. It should fail! */
rc = close(ports[i]);
EXPECT_EQ(ERR_NOT_FOUND, rc, "closing closed port");
/* wait on each individual port */ for (unsignedint i = first_free_handle_index; i < MAX_USER_HANDLES; i++) { /* wait with zero timeout */
rc = wait(ports[i], &event, 0);
EXPECT_EQ(ERR_TIMED_OUT, rc, "zero timeout");
/* wait on all ports with zero timeout */
rc = wait_any(&event, 0);
EXPECT_EQ(ERR_TIMED_OUT, rc, "zero timeout");
/* wait on all ports with non-zero timeout*/
rc = wait_any(&event, 100);
EXPECT_EQ(ERR_TIMED_OUT, rc, "non-zero timeout");
/* close them all */ for (unsignedint i = first_free_handle_index; i < MAX_USER_HANDLES; i++) { /* close a valid port */
rc = close(ports[i]);
EXPECT_EQ(NO_ERROR, rc, "closing closed port");
ports[i] = INVALID_IPC_HANDLE;
}
}
/* try to connect to port with an empty name */
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
EXPECT_EQ(ERR_INVALID_ARGS, rc, "empty path");
/* try to connect to non-existing port */
sprintf(path, "%s.conn.%s", SRV_PATH_BASE, "blah-blah");
rc = connect(path, 0);
EXPECT_EQ(ERR_NOT_FOUND, rc, "non-existing path");
/* try to connect to non-existing port */
sprintf(path, "%s.conn.%s", SRV_PATH_BASE, "blah-blah");
rc = connect(path, IPC_CONNECT_ASYNC);
EXPECT_EQ(ERR_NOT_FOUND, rc, "non-existing path");
/* try to connect to port with very long name */ int len = sprintf(path, "%s.conn.", SRV_PATH_BASE); for (size_t i = len; i < sizeof(path); i++)
path[i] = 'a';
path[sizeof(path) - 1] = '\0';
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
EXPECT_EQ(ERR_INVALID_ARGS, rc, "long path");
for (unsignedint j = first_free_handle_index; j < MAX_USER_HANDLES; j++) { /* do several iterations to make sure we are not
not loosing handles */ for (unsignedint i = 0; i < countof(chans); i++) {
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
EXPECT_GT_ZERO(rc, "connect/close");
chans[i] = (handle_t)rc;
}
for (unsignedint i = 0; i < countof(chans); i++) {
rc = close(chans[i]);
EXPECT_EQ(NO_ERROR, rc, "connect/close");
}
}
}
/* Try to connect to port that we register ourself. Itisnotveryusefulscenario,justtomakesurethat
nothing bad is happening */
sprintf(path, "%s.main.%s", SRV_PATH_BASE, "selfie");
rc = port_create(path, 2, MAX_PORT_BUF_SIZE, IPC_PORT_ALLOW_TA_CONNECT);
EXPECT_GT_ZERO(rc, "selfie");
if (rc >= 0) {
handle_t test_port = rc;
/* Since we are single threaded we will always timeout *atwait_anyforsynchronousconnectascan'taccept.
*/
/* with zero timeout */
rc = sync_connect(path, 0);
EXPECT_EQ(ERR_TIMED_OUT, rc, "selfie sync");
/* since we did not call wait on port yet we have *2connectionrequestspending(attachedtoport) *teareddownbypeer(us),annowremovedfromthe *port-thereshouldbenoeventswaiting.
*/
uevent_t event;
EXPECT_EQ(ERR_TIMED_OUT, wait_any(&event, 0));
/* retry using a couple of closed async connections */
rc = connect(path, IPC_CONNECT_ASYNC);
EXPECT_GT(rc, 0, "selfie async");
/* retry with a pending then closed async connection */
rc = connect(path, IPC_CONNECT_ASYNC);
EXPECT_GT(rc, 0, "selfie async");
rc = close(rc);
EXPECT_EQ(0, rc, "selfie async");
/* try accepting a pending connection, that was already closed */
rc = accept(test_port, &peer_uuid);
EXPECT_EQ(ERR_NO_MSG, rc, "accept async");
/* retry with a pending async connection */
rc = connect(path, IPC_CONNECT_ASYNC);
EXPECT_GT(rc, 0, "selfie async");
handle_t client_port = rc;
unsignedint exp_event = IPC_HANDLE_POLL_READY;
int rc = wait_any(&event, INFINITE_TIME);
EXPECT_EQ(NO_ERROR, rc, "wait on port");
EXPECT_EQ(test_port, event.handle, "wait on port");
EXPECT_EQ(exp_event, event.event, "wait on port");
if (rc == NO_ERROR && (event.event & IPC_HANDLE_POLL_READY)) { /* close the connection */
rc = close(client_port);
EXPECT_EQ(0, rc, "selfie async");
/* we had a pending connection, but it is already closed */
rc = accept(test_port, &peer_uuid);
EXPECT_EQ(ERR_NO_MSG, rc, "accept");
/* close selfie port */
rc = close(test_port);
EXPECT_EQ(NO_ERROR, rc, "close selfie");
}
}
TEST(IPC_LOCAL, connect_access) { int rc; char path[MAX_PORT_PATH_LEN];
/* open connection to NS only accessible service */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "ns_only");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
/* It is expected to fail */
EXPECT_EQ(ERR_ACCESS_DENIED, rc, "connect to ns_only");
if (rc >= 0)
close((handle_t)rc);
/* open connection to TA only accessible service */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "ta_only");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
/* it is expected to succeed */
EXPECT_GT_ZERO(rc, "connect to ta_only");
/* accept on non-existing handle that is in valid range */ for (unsignedint i = first_free_handle_index; i < MAX_USER_HANDLES; i++) {
rc = accept(handle_base + i, &peer_uuid);
EXPECT_EQ(ERR_NOT_FOUND, rc, "accept on invalid handle");
/* poke connect service to initiate connections to us */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "connect");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT); if (rc >= 0)
close((handle_t)rc);
/* handle incoming connections */ for (unsignedint i = first_free_handle_index; i < MAX_USER_HANDLES; i++) {
rc = wait_any(&event, 1000);
EXPECT_EQ(NO_ERROR, rc, "accept test");
EXPECT_EQ(IPC_HANDLE_POLL_READY, event.event, "accept test");
/* accept connection - should fail because we do not
have any room for handles */
rc = accept(event.handle, &peer_uuid);
EXPECT_EQ(ERR_NO_RESOURCES, rc, "accept test");
/* free 1 handle so we have room and repeat test */
rc = close(ports[first_free_handle_index]);
EXPECT_EQ(NO_ERROR, 0, "close accept test");
ports[2] = INVALID_IPC_HANDLE;
/* poke connect service to initiate connections to us */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "connect");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT); if (rc >= 0)
close((handle_t)rc);
/* handle incoming connections */ for (unsignedint i = first_free_handle_index; i < MAX_USER_HANDLES - 1;
i++) {
rc = wait_any(&event, 3000);
EXPECT_EQ(NO_ERROR, rc, "accept test");
EXPECT_EQ(IPC_HANDLE_POLL_READY, event.event, "accept test");
/* close them all */ for (unsignedint i = first_free_handle_index + 1; i < MAX_USER_HANDLES;
i++) { /* close a valid port */
rc = close(ports[i]);
EXPECT_EQ(NO_ERROR, rc, "close port");
ports[i] = INVALID_IPC_HANDLE;
}
}
/* create a port */
sprintf(path, "%s.port.accept%d", SRV_PATH_BASE, first_free_handle_index);
rc = port_create(path, 2, MAX_PORT_BUF_SIZE, IPC_PORT_ALLOW_TA_CONNECT);
EXPECT_GT_ZERO(rc, "max ports");
port = (handle_t)rc;
/* set the cookie */
rc = set_cookie(port, (void*)(COOKIE_BASE + port));
EXPECT_EQ(NO_ERROR, rc, "set cookie on port");
/* poke connect service to initiate connections to us */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "connect");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT); if (rc >= 0)
close((handle_t)rc);
/* get_msg on non-existing handle that is in valid range. */ for (unsignedint i = first_free_handle_index; i < MAX_USER_HANDLES; i++) {
rc = get_msg(handle_base + i, &inf);
EXPECT_EQ(ERR_NOT_FOUND, rc, "get_msg on invalid handle");
}
/* calling get_msg on port handle should fail
because get_msg is only applicable to channels */
sprintf(path, "%s.main.%s", SRV_PATH_BASE, "datasink");
rc = port_create(path, 2, MAX_PORT_BUF_SIZE, IPC_PORT_ALLOW_TA_CONNECT);
EXPECT_GT_ZERO(rc, "create datasink port");
port = (handle_t)rc;
rc = get_msg(port, &inf);
EXPECT_EQ(ERR_INVALID_ARGS, rc, "get_msg on port");
close(port);
/* call get_msg on channel that do not have any pending messages */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "datasink");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
EXPECT_GT_ZERO(rc, "connect to datasink");
chan = (handle_t)rc;
rc = get_msg(chan, &inf);
EXPECT_EQ(ERR_NO_MSG, rc, "get_msg on empty channel");
/* put_msg on non-existing handle that is in valid range */ for (unsignedint i = first_free_handle_index; i < MAX_USER_HANDLES; i++) {
rc = put_msg(handle_base + i, 0);
EXPECT_EQ(ERR_NOT_FOUND, rc, "put_msg on invalid handle");
}
/* calling put_msg on port handle should fail
because put_msg is only applicable to channels */
sprintf(path, "%s.main.%s", SRV_PATH_BASE, "datasink");
rc = port_create(path, 2, MAX_PORT_BUF_SIZE, IPC_PORT_ALLOW_TA_CONNECT);
EXPECT_GT_ZERO(rc, "create datasink port");
port = (handle_t)rc;
/* call put_msg on channel that do not have any pending messages */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "datasink");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
EXPECT_GT_ZERO(rc, "connect to datasink");
chan = (handle_t)rc;
/* open connection to datasink service */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "datasink");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
EXPECT_GT_ZERO(rc, "connect to datasink");
if (rc >= 0) {
chan = (handle_t)rc; for (unsignedint i = 0; i < 10000; i++) {
rc = send_msg(chan, &msg); if (rc == ERR_NOT_ENOUGH_BUFFER) { /* wait for room */
uevent_t uevt; unsignedint exp_event = IPC_HANDLE_POLL_SEND_UNBLOCKED;
rc = wait(chan, &uevt, 1000);
EXPECT_EQ(NO_ERROR, rc, "waiting for space");
EXPECT_EQ(chan, uevt.handle, "waiting for space");
EXPECT_EQ(exp_event, uevt.event, "waiting for space");
} else {
EXPECT_EQ(64, rc, "send_msg bulk")
} if (HasFailure()) {
TLOGI("%s: abort (rc = %d) test\n", __func__, rc); break;
}
}
rc = close(chan);
EXPECT_EQ(NO_ERROR, rc, "close channel");
}
}
/* init msg to empty message */
memset(&msg, 0, sizeof(msg));
/* send_msg on invalid (negative value) handle */
rc = send_msg(INVALID_IPC_HANDLE, &msg);
EXPECT_EQ(ERR_BAD_HANDLE, rc, "send_msg on invalid handle");
/* calling send_msg with NULL msg should fail for any handle */
rc = send_msg(INVALID_IPC_HANDLE, NULL);
EXPECT_EQ(ERR_FAULT, rc, "send_msg on NULL msg");
/* calling send_msg with NULL msg should fail for any handle */
rc = send_msg(MAX_USER_HANDLES, NULL);
EXPECT_EQ(ERR_FAULT, rc, "send_msg on NULL msg");
/* send_msg on non-existing handle that is in valid range */ for (unsignedint i = first_free_handle_index; i < MAX_USER_HANDLES; i++) {
rc = send_msg(handle_base + i, &msg);
EXPECT_EQ(ERR_NOT_FOUND, rc, "send on invalid handle");
/* calling send_msg with NULL msg should fail for any handle */
rc = send_msg(handle_base + i, NULL);
EXPECT_EQ(ERR_FAULT, rc, "send_msg on NULL msg");
}
/* calling send_msg on port handle should fail
because send_msg is only applicable to channels */
sprintf(path, "%s.main.%s", SRV_PATH_BASE, "datasink");
rc = port_create(path, 2, MAX_PORT_BUF_SIZE, IPC_PORT_ALLOW_TA_CONNECT);
EXPECT_GT_ZERO(rc, "create datasink port");
port = (handle_t)rc;
rc = send_msg(port, &msg);
EXPECT_EQ(ERR_INVALID_ARGS, rc, "send_msg on port");
close(port);
/* open connection to datasink service */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "datasink");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
EXPECT_GT_ZERO(rc, "connect to datasink");
chan = (handle_t)rc;
/* set num_iov to non zero but keep iov ptr NULL */
msg.num_iov = 1;
msg.iov = NULL;
rc = send_msg(chan, &msg);
EXPECT_EQ(ERR_FAULT, rc, "sending bad iovec array");
/* send msg with iovec with bad base ptr */
iov[0].iov_len = sizeof(buf) / 2;
iov[0].iov_base = NULL;
iov[1].iov_len = sizeof(buf) / 2;
iov[1].iov_base = NULL;
msg.num_iov = 2;
msg.iov = iov;
rc = send_msg(chan, &msg);
EXPECT_EQ(ERR_FAULT, rc, "sending bad iovec");
/* send msg with iovec with bad base ptr */
iov[0].iov_len = sizeof(buf) / 2;
iov[0].iov_base = buf;
iov[1].iov_len = sizeof(buf) / 2;
iov[1].iov_base = NULL;
msg.num_iov = 2;
msg.iov = iov;
rc = send_msg(chan, &msg);
EXPECT_EQ(ERR_FAULT, rc, "sending bad iovec");
rc = read_msg(handle_base + MAX_USER_HANDLES + 1, 0, 0, &rx_msg);
EXPECT_EQ(ERR_BAD_HANDLE, rc, "read_msg on bad handle");
rc = read_msg(handle_base - 1, 0, 0, &rx_msg);
EXPECT_EQ(ERR_BAD_HANDLE, rc, "read_msg on bad handle");
/* calling read_msg with NULL msg should fail for any handle */
rc = read_msg(handle_base + MAX_USER_HANDLES, 0, 0, NULL);
EXPECT_EQ(ERR_FAULT, rc, "read_msg on NULL msg");
/* send_msg on non-existing handle that is in valid range */ for (unsignedint i = first_free_handle_index; i < MAX_USER_HANDLES; i++) {
rc = read_msg(handle_base + i, 0, 0, &rx_msg);
EXPECT_EQ(ERR_NOT_FOUND, rc, "read_msg on non existing handle");
/* calling send_msg with NULL msg should fail for any handle */
rc = read_msg(handle_base + i, 0, 0, NULL);
EXPECT_EQ(ERR_FAULT, rc, "read_msg on NULL msg");
}
/* calling read_msg on port handle should fail
because read_msg is only applicable to channels */
sprintf(path, "%s.main.%s", SRV_PATH_BASE, "datasink");
rc = port_create(path, 2, MAX_PORT_BUF_SIZE, IPC_PORT_ALLOW_TA_CONNECT);
EXPECT_GT_ZERO(rc, "create datasink port");
port = (handle_t)rc;
/* open connection to echo service */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "echo");
rc = param_connect(path, IPC_CONNECT_WAIT_FOR_PORT, _state->test_param);
EXPECT_GT_ZERO(rc, "connect to echo");
/* TODO(b/458749193): High overhead on @wait over vsock makes 20k messages unreasonable */ if (_state->test_param == TIPC_TEST_PARAMETER_VSOCK) {
msg_cnt = 50;
}
/* send/receive messages synchronously */
tx_cnt = msg_cnt; while (tx_cnt) { /* send a message */
rc = send_msg(chan, &tx_msg);
EXPECT_EQ(64, rc, "sending msg to echo");
/* wait for response */
rc = wait(chan, &uevt, 1000);
EXPECT_EQ(NO_ERROR, rc, "waiting on echo response");
EXPECT_EQ(chan, uevt.handle, "wait on channel");
/* get a reply */
rc = get_msg(chan, &inf);
EXPECT_EQ(NO_ERROR, rc, "getting echo msg");
/* send/receive messages asynchronously */
tx_cnt = rx_cnt = msg_cnt; while (tx_cnt || rx_cnt) { /* send messages until all buffers are full */ while (tx_cnt) {
rc = send_msg(chan, &tx_msg); if (rc == ERR_NOT_ENOUGH_BUFFER) break; /* no more space */
EXPECT_EQ(64, rc, "sending msg to echo"); if (rc != 64) goto abort_test;
tx_cnt--;
}
/* wait for reply msg or room */
rc = wait(chan, &uevt, 1000);
EXPECT_EQ(NO_ERROR, rc, "waiting for reply");
EXPECT_EQ(chan, uevt.handle, "wait on channel");
/* drain all messages */ while (rx_cnt) { /* get a reply */
rc = get_msg(chan, &inf); if (rc == ERR_NO_MSG) break; /* no more messages */
TEST(IPC_LOCAL, DISABLED_WITH_COVERAGE(dup_no_resources)) { int rc;
handle_t hsets[MAX_USER_HANDLES];
/* create maximum number of handle sets */ for (unsignedint i = first_free_handle_index; i < MAX_USER_HANDLES; i++) {
hsets[i] = handle_set_create();
EXPECT_GE_ZERO((int)hsets[i], "create handle set");
}
rc = dup(hsets[first_free_handle_index]);
EXPECT_EQ(ERR_NO_RESOURCES, rc, "no more handles");
/* free 1 handle so we have room and repeat test */
rc = close(hsets[first_free_handle_index]);
EXPECT_EQ(NO_ERROR, rc, "close one set");
hsets[first_free_handle_index] = INVALID_IPC_HANDLE;
/* the only free handle here should be first_free_handle_index */
rc = dup(hsets[first_free_handle_index + 1]);
EXPECT_EQ(handle_base + first_free_handle_index, rc);
close(rc);
/* close them all */ for (unsignedint i = first_free_handle_index + 1; i < MAX_USER_HANDLES;
i++) { /* close a valid set */
rc = close(hsets[i]);
EXPECT_EQ(NO_ERROR, rc, "close set");
hsets[i] = INVALID_IPC_HANDLE;
}
}
/* send and wait a bit */
rc = send_msg(hchan1, &msg);
EXPECT_EQ(64, rc, "send handle");
trusty_nanosleep(0, 0, 100 * MSEC);
/* send it again and close it */
rc = send_msg(hchan1, &msg);
EXPECT_EQ(64, rc, "send handle");
rc = close(hchan2);
EXPECT_EQ(NO_ERROR, rc, "close chan2");
/* prepare test buffer */
fill_test_buf(buf0, sizeof(buf0), 0x55);
/* open connection to echo service */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "echo");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
EXPECT_GT_ZERO(rc, "connect to echo");
ABORT_IF_NOT_OK(err_connect1);
hchan1 = (handle_t)rc;
/* open second connection to echo service */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "echo");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
EXPECT_GT_ZERO(rc, "connect to echo");
ABORT_IF_NOT_OK(err_connect2);
hchan2 = (handle_t)rc;
for (unsignedint i = 0; (i < 10000) && !HasFailure(); i++) { while (!HasFailure()) {
rc = send_msg(hchan1, &msg); if (rc == ERR_NOT_ENOUGH_BUFFER) { /* wait for room */
uevent_t uevt; unsignedint exp_event = IPC_HANDLE_POLL_SEND_UNBLOCKED;
rc = wait(hchan1, &uevt, 10000);
EXPECT_EQ(NO_ERROR, rc, "waiting for space");
EXPECT_EQ(hchan1, uevt.handle, "waiting for space");
EXPECT_EQ(exp_event, uevt.event, "waiting for space");
} else {
EXPECT_EQ(64, rc, "send_msg bulk"); break;
}
}
}
rc = close(hchan2);
EXPECT_EQ(NO_ERROR, rc, "close chan2");
/* repeat the same while closing handle after sending it */ for (unsignedint i = 0; (i < 10000) && !HasFailure(); i++) {
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
EXPECT_GT_ZERO(rc, "connect to datasink");
ABORT_IF_NOT_OK(err_connect2);
hchan2 = (handle_t)rc;
/* prepare test buffer */
fill_test_buf(buf0, sizeof(buf0), 0x55);
/* open connection to echo service */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "echo");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
EXPECT_GT_ZERO(rc, "connect to echo");
ABORT_IF_NOT_OK(err_connect1);
hchan1 = (handle_t)rc;
/* open second connection to echo service */
sprintf(path, "%s.srv.%s", SRV_PATH_BASE, "echo");
rc = connect(path, IPC_CONNECT_WAIT_FOR_PORT);
EXPECT_GT_ZERO(rc, "connect to echo");
ABORT_IF_NOT_OK(err_connect2);
hchan2 = (handle_t)rc;
/* send the same handle 10000 times */ for (unsignedint i = 0; (i < 10000) && !HasFailure(); i++) { /* send message with handle */
iov.iov_base = buf0;
iov.iov_len = sizeof(buf0);
msg.iov = &iov;
msg.num_iov = 1;
msg.handles = &hchan2;
msg.num_handles = 1;
while (!HasFailure()) {
rc = send_msg(hchan1, &msg);
EXPECT_EQ(64, rc, "send_handle"); if (rc == ERR_NOT_ENOUGH_BUFFER) { /* wait for room */
uevent_t uevt; unsignedint exp_event = IPC_HANDLE_POLL_SEND_UNBLOCKED;
rc = wait(hchan1, &uevt, 10000);
EXPECT_EQ(NO_ERROR, rc, "waiting for space");
EXPECT_EQ(hchan1, uevt.handle, "waiting for space");
EXPECT_EQ(exp_event, uevt.event, "waiting for space");
} else {
EXPECT_EQ(64, rc, "send_msg bulk"); break;
}
}
/* wait for reply */
rc = wait(hchan1, &evt, 1000);
EXPECT_EQ(0, rc, "wait for reply");
EXPECT_EQ(hchan1, evt.handle, "event.handle");
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.51Bemerkung:
(vorverarbeitet am 2026-06-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.