Beispiel #1
0
ssize_t recvmmsg_assume_fd_is_nonblocking(
  value v_fd, struct iovec *iovecs, value v_count, value v_srcs, struct mmsghdr *hdrs)
{
  CAMLparam3(v_fd, v_count, v_srcs);
  CAMLlocal1(v_sockaddrs);
  size_t total_len = 0;
  union sock_addr_union addrs[Int_val(v_count)];
  int i;
  for (i = 0; i < Int_val(v_count); i++) {
    hdrs[i].msg_hdr.msg_name = (Is_block(v_srcs) ? &addrs[i].s_gen : 0);
    hdrs[i].msg_hdr.msg_namelen = (Is_block(v_srcs) ? sizeof(addrs[i]) : 0);

#if DEBUG
    fprintf(stderr, "i=%d, count=%d, is_some srcs=%d\n",
            i, Int_val(v_count), Is_block(v_srcs));
#endif
    total_len += iovecs[i].iov_len;

    hdrs[i].msg_hdr.msg_iov = &iovecs[i];
    hdrs[i].msg_hdr.msg_iovlen = 1;

    hdrs[i].msg_hdr.msg_control = 0;
    hdrs[i].msg_hdr.msg_controllen = 0;
    hdrs[i].msg_hdr.msg_flags = 0;
    /* We completely ignore msg_flags and ancillary data (msg_control)
       for now.  In the future, users may be interested in this. */
  }
  ssize_t n_read;
  /* pszilagyi: This is only 64k in unix_utils.h, which we will
     very quickly overrun with recvmmsg and then maybe Jumbo frames.
     bnigito has already observed the Pico feed filling over 32
     recvmmsg buffers in a single call, in a test scenario. */
  if (total_len > THREAD_IO_CUTOFF) {
    caml_enter_blocking_section();
      n_read = recvmmsg(Int_val(v_fd), hdrs, Int_val(v_count), 0, 0);
    caml_leave_blocking_section();
  }
  else n_read = recvmmsg(Int_val(v_fd), hdrs, Int_val(v_count), 0, 0);
  if (n_read == -1) {
    /* bnigito via pszilagyi: This prototype performance tweak saves
       the allocation of an exception in common cases, at the cost of
       conflating reception of an empty message with nothing to do. */
    if (errno == EWOULDBLOCK || errno == EAGAIN)
      n_read = -errno;
    else
      uerror("recvmmsg_assume_fd_is_nonblocking", Nothing);
  }
  else {
    if (Is_block(v_srcs)) {     /* Some */
      v_sockaddrs = Field(v_srcs, 0);
      for (i = 0; (unsigned)i < n_read && (unsigned)i < Wosize_val(v_sockaddrs); i++)
        Store_field(v_sockaddrs, i,
                    alloc_sockaddr(&addrs[i], hdrs[i].msg_hdr.msg_namelen, -1));
    }
  }
  CAMLreturnT(ssize_t, n_read);
}
Beispiel #2
0
bool Bridge_ReceiveDDPData(void)
{
    //    LogExcess(VB_E131BRIDGE, "Bridge_ReceiveData()\n");
    int msgcnt = recvmmsg(ddpSock, msgs, MAX_MSG, 0, nullptr);
    bool sync = false;
    while (msgcnt > 0) {
        for (int x = 0; x < msgcnt; x++) {
            sync |= Bridge_StoreDDPData((char*)buffers[x]);
        }
        msgcnt = recvmmsg(ddpSock, msgs, MAX_MSG, 0, nullptr);
    }
    return sync;
}
Beispiel #3
0
void on_response(evutil_socket_t fd, short what, void *arg) {
    struct client_state *state = arg;
    struct timespec recv_time, result;
    if (what&EV_READ) {
        int retval = recvmmsg(state->sock, state->msgs, state->vlen, MSG_WAITFORONE, NULL);
        if (retval < 0) {
          perror("recvmmsg()");
          exit(EXIT_FAILURE);
        }
        state->mps += retval;

        int i;
        for (i = 0; i < retval; i++) {
            state->bufs[i][state->msgs[i].msg_len] = 0;
            if (state->verbose) {
                printf("Received %d messages\n", retval);
                printf("%d %s %d\n", i+1, state->bufs[i], state->msgs[i].msg_len);
            }
        }
        gettime(&recv_time);
        int negative = timediff(&result, &recv_time, &state->send_time);
        if (negative) {
            fprintf(stderr, "Latency is negative\n");
        } else {
            double latency = (result.tv_sec + ((double)result.tv_nsec) / 1e9);
            fprintf(state->fp, "%.9f\n", latency);
        }
        // clean receiving buffer
        send_message(state, retval);
        gettime(&state->send_time);
    } if (what&EV_TIMEOUT) {
        send_message(state, state->vlen);
    }
}
Beispiel #4
0
int rcv_packet(int sock_raw, char *buffers, struct hdr_histogram *hist)
{
    struct mmsghdr msgs[NUM_BUFFERS];
    struct iovec entries[NUM_BUFFERS];
    struct {
        struct cmsghdr cm;
        char control[512];
    } control[NUM_BUFFERS];
    struct timespec timeout;
    int valid_pkts = 0;
    int npkts = 0;

    memset(&timeout, 0, sizeof(timeout));
    memset(msgs, 0, sizeof(msgs));
    for (int i = 0; i < NUM_BUFFERS; ++i) {
        entries[i].iov_base = &buffers[i * BUFFER_SIZE];
        entries[i].iov_len = BUFFER_SIZE;
        msgs[i].msg_hdr.msg_iov = &entries[i];
        msgs[i].msg_hdr.msg_iovlen = 1;
        msgs[i].msg_hdr.msg_control = &control[i];
        msgs[i].msg_hdr.msg_controllen = sizeof(control[i]);
    }

    npkts = recvmmsg(sock_raw, msgs, NUM_BUFFERS, MSG_WAITFORONE, &timeout);
    if (npkts < 0) {
        perror("recvmmsg()");
        return 0;
    }

    for (int i = 0; i < npkts; ++i) {
        if (process_msg(&msgs[i].msg_hdr, &buffers[i * BUFFER_SIZE], hist))
            valid_pkts += 1;
    }
    return valid_pkts;
}
Beispiel #5
0
int
udp_multirecv_read( udp_multirecv_t *um, int fd, int packets,
                    struct iovec **iovec )
{
  static char use_emul = 0;
  int n, i;
  if (um == NULL || iovec == NULL) {
    errno = EINVAL;
    return -1;
  }
  if (packets > um->um_packets)
    packets = um->um_packets;
  if (!use_emul) {
    n = recvmmsg(fd, (struct mmsghdr *)um->um_msg, packets, MSG_DONTWAIT, NULL);
  } else {
    n = -1;
    errno = ENOSYS;
  }
  if (n < 0 && errno == ENOSYS) {
    use_emul = 1;
    n = recvmmsg_i(fd, (struct mmsghdr *)um->um_msg, packets, MSG_DONTWAIT);
  }
  if (n > 0) {
    for (i = 0; i < n; i++)
      um->um_riovec[i].iov_len = ((struct mmsghdr *)um->um_msg)[i].msg_len;
    *iovec = um->um_riovec;
  }
  return n;
}
Beispiel #6
0
int main()
{
	struct sigaction sa = {0};
	sa.sa_handler = &timer_handler;
	sigaction(SIGALRM, &sa, NULL);

	struct itimerval timer = {0};
	timer.it_value.tv_sec = 1;
	timer.it_interval.tv_sec = 1;
	setitimer(ITIMER_REAL, &timer, NULL);

	struct sockaddr_storage listen_addr;
	net_gethostbyname(&listen_addr, "::", 1234);
	int fd = net_bind_udp(&listen_addr);

	struct mmsghdr messages[MAX_MSG] = {0};
	char buffers[MAX_MSG][MTU_SIZE];
	struct iovec iovecs[MAX_MSG] = {0};

	/* Setup recvmmsg data structures. */
	int i;
	for (i = 0; i < MAX_MSG; i++) {
		char *buf = &buffers[i][0];
		struct iovec *iovec = &iovecs[i];
		struct mmsghdr *msg = &messages[i];

		msg->msg_hdr.msg_iov = iovec;
		msg->msg_hdr.msg_iovlen = 1;

		iovec->iov_base = &buf[0];
		iovec->iov_len = MTU_SIZE;
	}

	while (1) {
		int r = recvmmsg(fd, messages, MAX_MSG, MSG_WAITFORONE, NULL);
		if (r == 0) {
			return 0;
		}

		if (r < 0) {
			if (errno == EINTR) {
				continue;
			}
			PFATAL("recv()");
		} else {
			for (i = 0; i < MAX_MSG; i++) {
				struct mmsghdr *msg = &messages[i];
				bytes += msg->msg_len;
				msg->msg_len = 0;
			}
			packets += r;
		}
	}
	close(fd);

	return 0;
}
Beispiel #7
0
static void graphite_run_recvmmsg(struct brubeck_graphite *graphite, int sock)
{
        const unsigned int SIM_PACKETS = graphite->mmsg_count;
        struct brubeck_server *server = graphite->sampler.server;

        struct brubeck_graphite_msg msg;
        struct brubeck_metric *metric;
        unsigned int i;

        struct iovec iovecs[SIM_PACKETS];
        struct mmsghdr msgs[SIM_PACKETS];

        memset(msgs, 0x0, sizeof(msgs));

        for (i = 0; i < SIM_PACKETS; ++i) {
                iovecs[i].iov_base = xmalloc(MAX_PACKET_SIZE);
                iovecs[i].iov_len = MAX_PACKET_SIZE - 1;
                msgs[i].msg_hdr.msg_iov = &iovecs[i];
                msgs[i].msg_hdr.msg_iovlen = 1;
        }

        log_splunk("sampler=graphite event=worker_online syscall=recvmmsg socket=%d", sock);

        for (;;) {
                int res = recvmmsg(sock, msgs, SIM_PACKETS, 0, NULL);

                if (res < 0) {
                        if (errno == EAGAIN || errno == EINTR)
                                continue;

                        log_splunk_errno("sampler=graphite event=failed_read");
                        brubeck_server_mark_dropped(server);
                        continue;
                }

                /* store stats */
                brubeck_atomic_add(&server->stats.metrics, SIM_PACKETS);
                brubeck_atomic_add(&graphite->sampler.inflow, SIM_PACKETS);

                for (i = 0; i < SIM_PACKETS; ++i) {
                        char *buf = msgs[i].msg_hdr.msg_iov->iov_base;
                        int len = msgs[i].msg_len;

                        if (brubeck_graphite_msg_parse(&msg, buf, len) < 0) {
                                log_splunk("sampler=graphite event=bad_key key='%.*s'", len, buf);
                                brubeck_server_mark_dropped(server);
                                continue;
                        }

                        metric = brubeck_metric_find(server, msg.key, msg.key_len, BRUBECK_MT_GAUGE);

                        if (metric != NULL)
                                brubeck_metric_record(metric, msg.value);
                }
        }

}
Beispiel #8
0
static int data_deliver_fn (
	int fd,
	int revents,
	void *data)
{
	struct totemknet_instance *instance = (struct totemknet_instance *)data;
	struct mmsghdr msg_recv[MAX_BUFFERS];
	struct iovec iov_recv[MAX_BUFFERS];
	struct sockaddr_storage system_from;
	int msgs_received;
	int i;

	for (i=0; i<MAX_BUFFERS; i++) {
		iov_recv[i].iov_base = instance->iov_buffer[i];
		iov_recv[i].iov_len = FRAME_SIZE_MAX;

		msg_recv[i].msg_hdr.msg_name = &system_from;
		msg_recv[i].msg_hdr.msg_namelen = sizeof (struct sockaddr_storage);
		msg_recv[i].msg_hdr.msg_iov = &iov_recv[i];
		msg_recv[i].msg_hdr.msg_iovlen = 1;
#ifdef HAVE_MSGHDR_CONTROL
		msg_recv[i].msg_hdr.msg_control = 0;
#endif
#ifdef HAVE_MSGHDR_CONTROLLEN
		msg_recv[i].msg_hdr.msg_controllen = 0;
#endif
#ifdef HAVE_MSGHDR_FLAGS
		msg_recv[i].msg_hdr.msg_flags = 0;
#endif
#ifdef HAVE_MSGHDR_ACCRIGHTS
		msg_recv[i].msg_hdr.msg_accrights = NULL;
#endif
#ifdef HAVE_MSGHDR_ACCRIGHTSLEN
		msg_recv[i].msg_hdr.msg_accrightslen = 0;
#endif
	}

	msgs_received = recvmmsg (fd, msg_recv, MAX_BUFFERS, MSG_NOSIGNAL | MSG_DONTWAIT, NULL);
	if (msgs_received == -1) {
		return (0);
	}

	for (i=0; i<msgs_received; i++) {

		instance->stats_recv += msg_recv[i].msg_len;

		/*
		 * Handle incoming message
		 */
		instance->totemknet_deliver_fn (
			instance->context,
			instance->iov_buffer[i],
			msg_recv[i].msg_len);
	}
	return (0);
}
Beispiel #9
0
extern int totemknet_recv_mcast_empty (
	void *knet_context)
{
	struct totemknet_instance *instance = (struct totemknet_instance *)knet_context;
	unsigned int res;
	struct sockaddr_storage system_from;
	struct mmsghdr msg_recv[MAX_BUFFERS];
	struct iovec iov_recv[MAX_BUFFERS];
	struct pollfd ufd;
	int nfds;
	int msg_processed = 0;
	int i;

	for (i=0; i<MAX_BUFFERS; i++) {
		iov_recv[i].iov_base = instance->iov_buffer[i];
		iov_recv[i].iov_len = FRAME_SIZE_MAX;

		msg_recv[i].msg_hdr.msg_name = &system_from;
		msg_recv[i].msg_hdr.msg_namelen = sizeof (struct sockaddr_storage);
		msg_recv[i].msg_hdr.msg_iov = &iov_recv[i];
		msg_recv[i].msg_hdr.msg_iovlen = 1;
#ifdef HAVE_MSGHDR_CONTROL
		msg_recv[i].msg_hdr.msg_control = 0;
#endif
#ifdef HAVE_MSGHDR_CONTROLLEN
		msg_recv[i].msg_hdr.msg_controllen = 0;
#endif
#ifdef HAVE_MSGHDR_FLAGS
		msg_recv[i].msg_hdr.msg_flags = 0;
#endif
#ifdef HAVE_MSGHDR_ACCRIGHTS
		msg_recv[i].msg_hdr.msg_accrights = NULL;
#endif
#ifdef HAVE_MSGHDR_ACCRIGHTSLEN
		msg_recv[i].msg_hdr.msg_accrightslen = 0;
#endif
	}

	do {
		ufd.fd = instance->knet_fd;
		ufd.events = POLLIN;
		nfds = poll (&ufd, 1, 0);
		if (nfds == 1 && ufd.revents & POLLIN) {
			res = recvmmsg (instance->knet_fd, msg_recv, MAX_BUFFERS, MSG_NOSIGNAL | MSG_DONTWAIT, NULL);
			if (res != -1) {
				msg_processed = 1;
			} else {
				msg_processed = -1;
			}
		}
	} while (nfds == 1);

	return (msg_processed);
}
Beispiel #10
0
static void statsd_run_recvmmsg(struct brubeck_statsd *statsd, int sock)
{
	const unsigned int SIM_PACKETS = statsd->mmsg_count;
	struct brubeck_server *server = statsd->sampler.server;

	struct brubeck_statsd_msg msg;
	struct brubeck_metric *metric;
	unsigned int i;

	struct iovec iovecs[SIM_PACKETS];
	struct mmsghdr msgs[SIM_PACKETS];

	memset(msgs, 0x0, sizeof(msgs));

	for (i = 0; i < SIM_PACKETS; ++i) {
		iovecs[i].iov_base = xmalloc(MAX_PACKET_SIZE);
		iovecs[i].iov_len = MAX_PACKET_SIZE;
		msgs[i].msg_hdr.msg_iov = &iovecs[i];
		msgs[i].msg_hdr.msg_iovlen = 1;
	}

	log_splunk("sampler=statsd event=worker_online syscall=recvmmsg socket=%d", sock);

	for (;;) {
		int res = recvmmsg(sock, msgs, SIM_PACKETS, 0, NULL);

		if (res == EAGAIN || res == EINTR || res == 0)
			continue;

		/* store stats */
		brubeck_atomic_add(&server->stats.metrics, SIM_PACKETS);
		brubeck_atomic_add(&statsd->sampler.inflow, SIM_PACKETS);

		if (res < 0) {
			brubeck_server_mark_dropped(server);
			continue;
		}

		for (i = 0; i < SIM_PACKETS; ++i) {
			char *buf = msgs[i].msg_hdr.msg_iov->iov_base;
			int len = msgs[i].msg_len;

			if (brubeck_statsd_msg_parse(&msg, buf, len) < 0) {
				brubeck_server_mark_dropped(server);
				log_splunk("sampler=statsd event=packet_drop");
				continue;
			}

			metric = brubeck_metric_find(server, msg.key, msg.key_len, msg.type);
			if (metric != NULL)
				brubeck_metric_record(metric, msg.value);
		}
	}
}
Beispiel #11
0
int
udp_multirecv_read( udp_multirecv_t *um, int fd, int packets,
                    struct iovec **iovec )
{
  int n, i;
  if (packets > um->um_packets)
    packets = um->um_packets;
  n = recvmmsg(fd, (struct mmsghdr *)um->um_msg, packets, MSG_DONTWAIT, NULL);
  if (n > 0) {
    for (i = 0; i < n; i++)
      um->um_riovec[i].iov_len = ((struct mmsghdr *)um->um_msg)[i].msg_len;
    *iovec = um->um_riovec;
  }
  return n;
}
Beispiel #12
0
static int do_cmsg_generic(int child, int use_recvmmsg) {
  int fd = do_open(child);
  /* launder it through SCM_RIGHTS */
  char ch = 0;
  struct mmsghdr msgvec;
  struct msghdr* msg = &msgvec.msg_hdr;
  struct iovec iov;
  uint8_t cbuf[CMSG_SPACE(sizeof(fd))];
  struct cmsghdr* cmsg;
  int sockfds[2];

  test_assert(0 == socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds));

  iov.iov_base = "x";
  iov.iov_len = 1;
  memset(msg, 0, sizeof(*msg));
  msg->msg_iov = &iov;
  msg->msg_iovlen = 1;
  msg->msg_control = cbuf;
  msg->msg_controllen = sizeof(cbuf);
  cmsg = CMSG_FIRSTHDR(msg);
  cmsg->cmsg_level = SOL_SOCKET;
  cmsg->cmsg_type = SCM_RIGHTS;
  cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
  memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
  test_assert(1 == sendmsg(sockfds[1], msg, 0));

  iov.iov_base = &ch;
  if (use_recvmmsg) {
    test_assert(1 == recvmmsg(sockfds[0], &msgvec, 1, 0, NULL));
    test_assert(1 == msgvec.msg_len);
  } else {
    test_assert(1 == recvmsg(sockfds[0], msg, 0));
  }
  test_assert('x' == ch);
  cmsg = CMSG_FIRSTHDR(msg);
  test_assert(SOL_SOCKET == cmsg->cmsg_level && SCM_RIGHTS == cmsg->cmsg_type);
  memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));
  close(sockfds[0]);
  close(sockfds[1]);
  return fd;
}
Beispiel #13
0
static void statsd_run_recvmmsg(struct brubeck_statsd *statsd, int sock)
{
	const unsigned int SIM_PACKETS = statsd->mmsg_count;
	struct brubeck_server *server = statsd->sampler.server;

	unsigned int i;
	struct iovec iovecs[SIM_PACKETS];
	struct mmsghdr msgs[SIM_PACKETS];

	memset(msgs, 0x0, sizeof(msgs));

	for (i = 0; i < SIM_PACKETS; ++i) {
		iovecs[i].iov_base = xmalloc(MAX_PACKET_SIZE);
		iovecs[i].iov_len = MAX_PACKET_SIZE - 1;
		msgs[i].msg_hdr.msg_iov = &iovecs[i];
		msgs[i].msg_hdr.msg_iovlen = 1;
	}

	log_splunk("sampler=statsd event=worker_online syscall=recvmmsg socket=%d", sock);

	for (;;) {
		int res = recvmmsg(sock, msgs, SIM_PACKETS, 0, NULL);

		if (res < 0) {
			if (errno == EAGAIN || errno == EINTR)
				continue;

			log_splunk_errno("sampler=statsd event=failed_read");
			brubeck_stats_inc(server, errors);
			continue;
		}

		/* store stats */
		brubeck_atomic_add(&statsd->sampler.inflow, SIM_PACKETS);

		for (i = 0; i < SIM_PACKETS; ++i) {
			char *buf = msgs[i].msg_hdr.msg_iov->iov_base;
			char *end = buf + msgs[i].msg_len;
			brubeck_statsd_packet_parse(server, buf, end);
		}
	}
}
Beispiel #14
0
CAMLprim value
iobuf_recvmmsg_assume_fd_is_nonblocking_stub
(value v_fd, value v_iobufs, value v_recvmmsg_ctx)
{
  CAMLparam3(v_fd, v_iobufs, v_recvmmsg_ctx);
  CAMLlocal1(v_iobuf);
  value v_lo_min;
  unsigned i;
  int n_read;
  struct mmsghdr * hdrs;
  struct iovec   * iovecs;

  hdrs   = Recvmmsg_ctx_ptr(v_recvmmsg_ctx)->hdrs;
  iovecs = Recvmmsg_ctx_ptr(v_recvmmsg_ctx)->iovecs;
  n_read = recvmmsg(Int_val(v_fd), hdrs, Wosize_val(v_iobufs), 0, 0);

  for (i = 0; (int) i < n_read; i++) {
    v_iobuf = Field(v_iobufs, i);
    v_lo_min = Field(v_iobuf, iobuf_lo_min);

    /* Here we fail if the user has called set_bounds_and_buffer, replacing the underlying
     * bigstring after we've cached the pointer.
     */
    if (get_bstr(Field(v_iobuf, iobuf_buf), v_lo_min) !=
        hdrs[i].msg_hdr.msg_iov->iov_base) {
      n_read = -1;
      errno  = EINVAL;
    }
    else {
      /* Knowing the structure of an Iobuf record (which we already
       * are dependent on), we can use Field(v_iobuf, iobuf_lo) as an
       * lvalue and skip the caml_modify done by Store_field.
       */
      Field(v_iobuf, iobuf_lo) = v_lo_min;
      Field(v_iobuf, iobuf_hi) = Val_long(Long_val(v_lo_min) + hdrs[i].msg_len);
    }
  }
  if (n_read == -1)
    n_read = -errno;

  CAMLreturn(Val_int(n_read));
}
Beispiel #15
0
Datei: block.c Projekt: KurSh/rr
static void* reader_thread(void* dontcare) {
	char token = '!';
	int sock = sockfds[1];
	struct timeval ts;
	char c = '\0';
	int i;

	gettimeofday(&ts, NULL);

	atomic_puts("r: acquiring mutex ...");
	pthread_mutex_lock(&lock);
	atomic_puts("r:   ... releasing mutex");
	pthread_mutex_unlock(&lock);

	for (i = 0; i < 2; ++i) {
		atomic_puts("r: reading socket ...");
		gettimeofday(&ts, NULL);
		test_assert(1 == read(sock, &c, sizeof(c)));
		atomic_printf("r:   ... read '%c'\n", c);
		test_assert(c == token);
		++token;
	}
	/* TODO: readv() support */

	atomic_puts("r: recv'ing socket ...");
	gettimeofday(&ts, NULL);
	test_assert(1 == recv(sock, &c, sizeof(c), 0));
	atomic_printf("r:   ... recv'd '%c'\n", c);
	test_assert(c == token);
	++token;

	atomic_puts("r: recvfrom'ing socket ...");
	test_assert(1 == recvfrom(sock, &c, sizeof(c), 0, NULL, NULL));
	atomic_printf("r:   ... recvfrom'd '%c'\n", c);
	test_assert(c == token);
	++token;
	{
		struct sockaddr_un addr;
		socklen_t addrlen = sizeof(addr);

		atomic_puts("r: recvfrom(&sock)'ing socket ...");
		test_assert(1 == recvfrom(sock, &c, sizeof(c), 0,
					  &addr, &addrlen));
		atomic_printf("r:   ... recvfrom'd '%c' from sock len:%d\n",
			      c, addrlen);
		test_assert(c == token);
		/* socketpair() AF_LOCAL sockets don't identify
		 * themselves. */
		test_assert(addrlen == 0);
		++token;
	}
	{
		struct mmsghdr mmsg = {{ 0 }};
		struct iovec data = { 0 };
		int magic = ~msg_magic;
		int err, ret;

		data.iov_base = &magic;
		data.iov_len = sizeof(magic);
		mmsg.msg_hdr.msg_iov = &data;
		mmsg.msg_hdr.msg_iovlen = 1;

		atomic_puts("r: recvmsg with DONTWAIT ...");
		ret = recvmsg(sock, &mmsg.msg_hdr, MSG_DONTWAIT);
		err = errno;
		atomic_printf("r:  ... returned %d (%s/%d)\n",
			      ret, strerror(err), err);
		test_assert(-1 == ret && EWOULDBLOCK == err);

		atomic_puts("r: recmsg'ing socket ...");

		test_assert(0 < recvmsg(sock, &mmsg.msg_hdr, 0));
		atomic_printf("r:   ... recvmsg'd 0x%x\n", magic);
		test_assert(msg_magic == magic);

		magic = ~msg_magic;
		atomic_puts("r: recmmsg'ing socket ...");

		pthread_barrier_wait(&cheater_barrier);
		breakpoint();
		test_assert(1 == recvmmsg(sock, &mmsg, 1, 0, NULL));
		atomic_printf("r:   ... recvmmsg'd 0x%x (%u bytes)\n",
			      magic, mmsg.msg_len);
		test_assert(msg_magic == magic);
	}
	{
		struct msghdr msg = { 0 };
		struct iovec iovs[2];
		char c1 = '\0', c2 = '\0';

		iovs[0].iov_base = &c1;
		iovs[0].iov_len = sizeof(c1);
		iovs[1].iov_base = &c2;
		iovs[1].iov_len = sizeof(c2);

		msg.msg_iov = iovs;
		msg.msg_iovlen = sizeof(iovs) / sizeof(iovs[0]);

		atomic_puts("r: recmsg'ing socket with two iovs ...");
		test_assert(2 == recvmsg(sock, &msg, 0));
		atomic_printf("r:   ... recvmsg'd '%c' and '%c'\n", c1, c2);

		test_assert(c1 == token);
		token++;
		test_assert(c2 == token);
		token++;
	}
	{
		struct pollfd pfd;

		atomic_puts("r: polling socket ...");
		pfd.fd = sock;
		pfd.events = POLLIN;
		gettimeofday(&ts, NULL);
		poll(&pfd, 1, -1);
		atomic_puts("r:   ... done, doing nonblocking read ...");
		test_assert(1 == read(sock, &c, sizeof(c)));
		atomic_printf("r:   ... read '%c'\n", c);
		test_assert(c == token);
		++token;
	}
	{
		struct pollfd pfd;

		atomic_puts("r: polling socket ...");
		pfd.fd = sock;
		pfd.events = POLLIN;
		gettimeofday(&ts, NULL);
		ppoll(&pfd, 1, NULL, NULL);
		atomic_puts("r:   ... done, doing nonblocking read ...");
		test_assert(1 == read(sock, &c, sizeof(c)));
		atomic_printf("r:   ... read '%c'\n", c);
		test_assert(c == token);
		++token;
	}
	{
		fd_set fds;
		const struct timeval infinity = { 1 << 30, 0 };
		struct timeval tv = infinity;
		int ret;

		atomic_puts("r: select()ing socket ...");
		FD_ZERO(&fds);
		FD_SET(sock, &fds);
		ret = select(sock + 1, &fds, NULL, NULL, &tv);
		atomic_printf("r:   ... returned %d; tv { %ld, %ld }\n",
			      ret, tv.tv_sec, tv.tv_usec);
		test_assert(1 == ret);
		test_assert(FD_ISSET(sock, &fds));
		test_assert(0 < tv.tv_sec && tv.tv_sec < infinity.tv_sec);

		atomic_puts("r:   ... done, doing nonblocking read ...");
		test_assert(1 == read(sock, &c, sizeof(c)));
		atomic_printf("r:   ... read '%c'\n", c);
		test_assert(c == token);
		++token;
	}
	{
		int epfd;
		struct epoll_event ev;

		atomic_puts("r: epolling socket ...");
		test_assert(0 <= (epfd = epoll_create(1/*num events*/)));
		ev.events = EPOLLIN;
		ev.data.fd = sock;
		gettimeofday(&ts, NULL);
		test_assert(0 == epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd,
					   &ev));
		test_assert(1 == epoll_wait(epfd, &ev, 1, -1));
		atomic_puts("r:   ... done, doing nonblocking read ...");
		test_assert(sock == ev.data.fd);
		test_assert(1 == read(sock, &c, sizeof(c)));
		atomic_printf("r:   ... read '%c'\n", c);
		test_assert(c == token);
		++token;

		close(epfd);
	}
	{
		char* buf = (char*)malloc(num_sockbuf_bytes);
		ssize_t nwritten = 0;
		struct iovec iov;

		++token;
		memset(buf, token, num_sockbuf_bytes);

		atomic_printf("r: writing outbuf of size %d ...\n",
			      num_sockbuf_bytes);
		while (nwritten < num_sockbuf_bytes) {
			ssize_t this_write =
				write(sock, buf,
				      num_sockbuf_bytes - nwritten);
			atomic_printf("r:   wrote %d bytes this time\n",
				      this_write);
			nwritten += this_write;
		}

		++token;
		memset(buf, token, num_sockbuf_bytes);
		iov.iov_base = buf;
		iov.iov_len = num_sockbuf_bytes;
		atomic_printf("r: writev()ing outbuf of size %d ...\n",
			      num_sockbuf_bytes);
		while (iov.iov_len > 0) {
			ssize_t this_write = writev(sock, &iov, 1);
			atomic_printf("r:   wrote %d bytes this time\n",
				      this_write);
			iov.iov_len -= this_write;
		}

		free(buf);
	}

	atomic_puts("r: reading socket with masked signals ...");
	{
		sigset_t old_mask, mask;
		sigfillset(&mask);
		test_assert(0 == pthread_sigmask(SIG_BLOCK, &mask, &old_mask));

		test_assert(1 == read(sock, &c, sizeof(c)));

		test_assert(0 == pthread_sigmask(SIG_SETMASK, &old_mask, NULL));
	}
	++token;
	atomic_printf("r:   ... read '%c'\n", c);
	test_assert(c == token);

	/* Make the main thread wait on our join() */
	atomic_puts("r: sleeping ...");
	usleep(500000);

	return NULL;
}
Beispiel #16
0
int J1939SocketRead (int Socket, struct J1939FrameBag *Bags, unsigned int BagsCount, int TimeoutMs)
{
    struct mmsghdr msgs[BagsCount];
    struct iovec iovs[BagsCount];
    struct sockaddr_can addr[BagsCount];
    char ctrlmsgs[BagsCount][
            CMSG_SPACE(sizeof(struct timeval))
          + CMSG_SPACE(sizeof(__u8)) /* dest addr */
          + CMSG_SPACE(sizeof(__u64)) /* dest name */
          + CMSG_SPACE(sizeof(__u8)) /* priority */
          ];

    unsigned int i;
    for (i = 0; i < BagsCount; i++)
    {
        memset(&msgs[i], 0, sizeof(msgs[0]));
        memset(&iovs[i], 0, sizeof(iovs[0]));
        memset(&addr[i], 0, sizeof(addr[0]));

        msgs[i].msg_hdr.msg_name = &addr[i];
        msgs[i].msg_hdr.msg_namelen = sizeof(struct sockaddr_can);

        iovs[i].iov_base = (void *) &(Bags[i].Frame.data);
        iovs[i].iov_len = sizeof(Bags[i].Frame.data);
        msgs[i].msg_hdr.msg_iov = &iovs[i];
        msgs[i].msg_hdr.msg_iovlen = 1;

        msgs[i].msg_hdr.msg_control = &ctrlmsgs[i];
        msgs[i].msg_hdr.msg_controllen = sizeof(ctrlmsgs[0]);
        msgs[i].msg_hdr.msg_flags = 0;
    }

    struct timeval tNow, tEnd;
    for ( initTimers(&tNow, &tEnd, TimeoutMs); timercmp(&tNow, &tEnd, <=); gettimeofday (&tNow, NULL) )
    {
        int rcount;
        rcount = recvmmsg(Socket, msgs, BagsCount, MSG_DONTWAIT, NULL);
        if (rcount >= 0)
        {
            int i;
            for (i = 0; i < rcount; i ++)
            {
                struct timeval tv;
                struct cmsghdr *cmsg;

                for (cmsg = CMSG_FIRSTHDR(&msgs[i].msg_hdr);
                    cmsg;
                    cmsg = CMSG_NXTHDR(&msgs[i].msg_hdr,cmsg))
                {
                    switch (cmsg->cmsg_level) {
                    case SOL_SOCKET:
                        if (cmsg->cmsg_type == SO_TIMESTAMP)
                        {
                            tv = *(struct timeval *)CMSG_DATA(cmsg);
                            Bags[i].TimeStamp.seconds = tv.tv_sec;
                            Bags[i].TimeStamp.microseconds = tv.tv_usec;
                        }
                        else if (cmsg->cmsg_type == SO_RXQ_OVFL)
                            Bags[i].DroppedMessagesCount = *(__u32 *)CMSG_DATA(cmsg);
                        break;
                    case SOL_CAN_J1939:

                        break;
                    }
                }

                Bags[i].Frame.pgn = addr[i].can_addr.j1939.pgn;
                Bags[i].Frame.length = msgs[i].msg_len;

                if (msgs[i].msg_hdr.msg_flags & MSG_CONFIRM)
                    Bags[i].Flags |= (1 << 0);
            }
            return rcount;
        }
        else
        {
            int errsv = errno;
            if (errsv == EAGAIN)
            {
              usleep (100);
              continue;
            }
            else
              return errsv;
        }
    }
    return 0;
}
int aeron_udp_channel_transport_recvmmsg(
    aeron_udp_channel_transport_t *transport,
    struct mmsghdr *msgvec,
    size_t vlen,
    aeron_udp_transport_recv_func_t recv_func,
    void *clientd)
{
#if defined(HAVE_RECVMMSG)
    struct timespec tv = {.tv_nsec = 0, .tv_sec = 0};

    int result = recvmmsg(transport->fd, msgvec, vlen, 0, &tv);
    if (result < 0)
    {
        int err = errno;

        if (EINTR == err || EAGAIN == err)
        {
            return 0;
        }

        aeron_set_err(err, "recvmmsg: %s", strerror(err));
        return -1;
    }
    else if (0 == result)
    {
        return 0;
    }
    else
    {
        for (size_t i = 0, length = result; i < length; i++)
        {
            recv_func(
                clientd,
                transport->dispatch_clientd,
                msgvec[i].msg_hdr.msg_iov[0].iov_base,
                msgvec[i].msg_len,
                msgvec[i].msg_hdr.msg_name);
        }

        return result;
    }
#else
    int work_count = 0;

    for (size_t i = 0, length = vlen; i < length; i++)
    {
        ssize_t result = recvmsg(transport->fd, &msgvec[i].msg_hdr, 0);

        if (result < 0)
        {
            int err = errno;

            if (EINTR == err || EAGAIN == err)
            {
                break;
            }

            aeron_set_err(err, "recvmsg: %s", strerror(err));
            return -1;
        }
        if (0 == result)
        {
            break;
        }

        msgvec[i].msg_len = (unsigned int)result;
        recv_func(
            clientd,
            transport->dispatch_clientd,
            msgvec[i].msg_hdr.msg_iov[0].iov_base,
            msgvec[i].msg_len,
            msgvec[i].msg_hdr.msg_name);
        work_count++;
    }

    return work_count;
#endif
}

int aeron_udp_channel_transport_sendmmsg(
    aeron_udp_channel_transport_t *transport,
    struct mmsghdr *msgvec,
    size_t vlen)
{
#if defined(HAVE_RECVMMSG)
    int sendmmsg_result = sendmmsg(transport->fd, msgvec, vlen, 0);
    if (sendmmsg_result < 0)
    {
        aeron_set_err(errno, "sendmmsg: %s", strerror(errno));
        return -1;
    }

    return sendmmsg_result;
#else
    int result = 0;

    for (size_t i = 0, length = vlen; i < length; i++)
    {
        ssize_t sendmsg_result = sendmsg(transport->fd, &msgvec[i].msg_hdr, 0);
        if (sendmsg_result < 0)
        {
            aeron_set_err(errno, "sendmsg: %s", strerror(errno));
            return -1;
        }

        msgvec[i].msg_len = (unsigned int)sendmsg_result;

        if (0 == sendmsg_result)
        {
            break;
        }

        result++;
    }

    return result;
#endif
}
Beispiel #18
0
static void
ind_ovs_handle_port_upcalls(struct ind_ovs_upcall_thread *thread,
                            struct ind_ovs_port *port)
{
    int fd = nl_socket_get_fd(port->notify_socket);
    int count = 0; /* total messages processed */

    while (count < 128) {
        /* Fast recv into our preallocated messages */
        int n = recvmmsg(fd, thread->msgvec, NUM_UPCALL_BUFFERS, 0, NULL);
        if (n < 0) {
            if (errno == EAGAIN) {
                break;
            } else {
                continue;
            }
        }

        thread->tx_queue_len = 0;

        ind_ovs_fwd_read_lock();

        int i;
        for (i = 0; i < n; i++) {
            struct nl_msg *msg = thread->msgs[i];
            struct nlmsghdr *nlh = nlmsg_hdr(msg);

            /*
            * HACK to workaround OVS not using nlmsg_end().
            * This size is padded to 4 byte alignment which
            * nlmsg_len shouldn't be. This hasn't confused
            * the parser yet. Worse is that in the case of
            * multipart messages the buffer returned by
            * read contains multiple messages. Luckily the
            * only buggy messages are from the packet family,
            * which doesn't use any multipart messages.
            */
            /* Don't mess with messages that aren't broken. */
            int len = thread->msgvec[i].msg_len;
            if (nlh->nlmsg_len + nlmsg_padlen(nlh->nlmsg_len) != len) {
                //LOG_TRACE("fixup size: nlh->nlmsg_len=%d pad=%d len=%d", nlh->nlmsg_len, nlmsg_padlen(nlh->nlmsg_len), len);
                nlh->nlmsg_len = len;
            }

            ind_ovs_handle_one_upcall(thread, port, msg);
        }

        ind_ovs_fwd_read_unlock();

        struct msghdr msghdr = { 0 };
        msghdr.msg_iov = thread->tx_queue;
        msghdr.msg_iovlen = thread->tx_queue_len;
        (void) sendmsg(fd, &msghdr, 0);

        count += n;

        if (n != NUM_UPCALL_BUFFERS) {
            break;
        }
    }

    /* See ind_ovs_upcall_quiesce */
    /* TODO remove locking from the fast path */
    pthread_mutex_lock(&port->quiesce_lock);
    if (port->quiescing) {
        port->quiescing = false;
        pthread_cond_signal(&port->quiesce_cvar);
        pthread_mutex_unlock(&port->quiesce_lock);
        return;
    }
    pthread_mutex_unlock(&port->quiesce_lock);

    ind_ovs_upcall_rearm(port);
}
Beispiel #19
0
CAMLprim value bigstring_recvmmsg_assume_fd_is_nonblocking_stub(
  value v_fd, value v_iovecs, value v_count, value v_srcs, value v_lens)
{
  CAMLparam5(v_fd, v_iovecs, v_count, v_srcs, v_lens);
  CAMLlocal5(v_iovec, v_buf, v_pos, v_len, v_sockaddrs);
  size_t total_len = 0;
  struct mmsghdr hdrs[Long_val(v_count)];
  union sock_addr_union addrs[Long_val(v_count)];
  struct iovec iovecs[Long_val(v_count)];
  unsigned i;
  ssize_t n_read;
  int save_source_addresses;
  int fd;
  unsigned int count;

  save_source_addresses = Is_block(v_srcs);
  fd = Int_val(v_fd);
  count = (unsigned int) Long_val(v_count);
  if (count != Long_val(v_count)) {
    caml_invalid_argument("bigstring_recvmmsg_assume_fd_is_nonblocking_stub: "
                          "v_count exceeds unsigned int");
  }
  if (!Is_block(v_lens)) {
    caml_invalid_argument("bigstring_recvmmsg_assume_fd_is_nonblocking_stub: "
                          "v_lens is not an array");
  }
  if (Wosize_val(v_lens) < count) {
    caml_invalid_argument("bigstring_recvmmsg_assume_fd_is_nonblocking_stub: "
                          "length v_lens < count");
  }

  for (i = 0; i < count; i++) {
    hdrs[i].msg_hdr.msg_name = (save_source_addresses ? &addrs[i].s_gen : 0);
    hdrs[i].msg_hdr.msg_namelen = sizeof(addrs[i]);

    v_iovec = Field(v_iovecs, i);
    v_buf = Field(v_iovec, 0);
    v_pos = Field(v_iovec, 1);
    v_len = Field(v_iovec, 2);

    iovecs[i].iov_base = get_bstr(v_buf, v_pos);
    iovecs[i].iov_len = Long_val(v_len);
    total_len += iovecs[i].iov_len;

    hdrs[i].msg_hdr.msg_iov = &iovecs[i];
    hdrs[i].msg_hdr.msg_iovlen = 1;

    hdrs[i].msg_hdr.msg_control = 0;
    hdrs[i].msg_hdr.msg_flags = 0;
  }

  if (total_len > THREAD_IO_CUTOFF) {
    caml_enter_blocking_section();
      n_read = recvmmsg(fd, hdrs, count, 0, 0);
    caml_leave_blocking_section();
  }
  else {
    n_read = recvmmsg(fd, hdrs, count, 0, 0);
  }

  if (n_read > count) {
    caml_failwith("bigstring_recvmmsg_assume_fd_is_nonblocking_stub: "
                  "recvmmsg unexpectedly returned n_read > count");
  }

  if (n_read == -1) {
    uerror("recvmmsg_assume_fd_is_nonblocking", Nothing);
  }
  else {
    if (save_source_addresses) {
      v_sockaddrs = Field(v_srcs, 0);
      if (!Is_block(v_sockaddrs)) {
        caml_invalid_argument("bigstring_recvmmsg_assume_fd_is_nonblocking_stub: "
                              "v_sockaddrs is not an array");
      }
      if (Wosize_val(v_sockaddrs) < count) {
        caml_invalid_argument("bigstring_recvmmsg_assume_fd_is_nonblocking_stub: "
                              "length v_sockaddrs < count");
      }

      for (i = 0; i < n_read; i++) {
        value addr = alloc_sockaddr(&addrs[i], hdrs[i].msg_hdr.msg_namelen, -1);
        Store_field(v_sockaddrs, i, addr);
      }
    }
    for (i = 0; i < n_read; i++) {
      Field(v_lens, i) = Val_long(hdrs[i].msg_len);
    }
  }
  CAMLreturn(Val_long(n_read));
}
Beispiel #20
0
static void* reader_thread(void* dontcare) {
  char token = '!';
  int sock = sockfds[1];
  struct timeval ts;
  char c = '\0';
  int i;

  gettimeofday(&ts, NULL);

  atomic_puts("r: acquiring mutex ...");
  pthread_mutex_lock(&lock);
  atomic_puts("r:   ... releasing mutex");
  pthread_mutex_unlock(&lock);

  for (i = 0; i < 2; ++i) {
    atomic_puts("r: reading socket ...");
    gettimeofday(&ts, NULL);
    test_assert(1 == read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  /* TODO: readv() support */

  atomic_puts("r: recv'ing socket ...");
  gettimeofday(&ts, NULL);
  test_assert(1 == recv(sock, &c, sizeof(c), 0));
  atomic_printf("r:   ... recv'd '%c'\n", c);
  test_assert(c == token);
  ++token;

  atomic_puts("r: recvfrom'ing socket ...");
  test_assert(1 == recvfrom(sock, &c, sizeof(c), 0, NULL, NULL));
  atomic_printf("r:   ... recvfrom'd '%c'\n", c);
  test_assert(c == token);
  ++token;
  {
    struct sockaddr_un addr;
    socklen_t addrlen = sizeof(addr);

    atomic_puts("r: recvfrom(&sock)'ing socket ...");
    test_assert(1 == recvfrom(sock, &c, sizeof(c), 0, &addr, &addrlen));
    atomic_printf("r:   ... recvfrom'd '%c' from sock len:%d\n", c, addrlen);
    test_assert(c == token);
    /* socketpair() AF_LOCAL sockets don't identify
     * themselves. */
    test_assert(addrlen == 0);
    ++token;
  }
  {
    struct mmsghdr mmsg = { { 0 } };
    struct iovec data = { 0 };
    int magic = ~msg_magic;
    int err, ret;

    data.iov_base = &magic;
    data.iov_len = sizeof(magic);
    mmsg.msg_hdr.msg_iov = &data;
    mmsg.msg_hdr.msg_iovlen = 1;

    struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CTRLMSG_LEN);
    mmsg.msg_hdr.msg_control = cmptr;
    mmsg.msg_hdr.msg_controllen = CTRLMSG_LEN;

    atomic_puts("r: recvmsg with DONTWAIT ...");
    ret = recvmsg(sock, &mmsg.msg_hdr, MSG_DONTWAIT);
    err = errno;
    atomic_printf("r:  ... returned %d (%s/%d)\n", ret, strerror(err), err);
    test_assert(-1 == ret);
    test_assert(EWOULDBLOCK == err);
    test_assert(mmsg.msg_hdr.msg_iov == &data);

    atomic_puts("r: recmsg'ing socket ...");

    test_assert(0 < recvmsg(sock, &mmsg.msg_hdr, 0));
    atomic_printf("r:   ... recvmsg'd 0x%x\n", magic);
    test_assert(msg_magic == magic);
    test_assert(mmsg.msg_hdr.msg_iov == &data);

    int fd = *(int*)CMSG_DATA(cmptr);
    struct stat fs_new, fs_old;
    fstat(fd, &fs_new);
    fstat(STDERR_FILENO, &fs_old);
    // check if control msg was send successfully
    test_assert(
        fs_old.st_dev == fs_new.st_dev && fs_old.st_ino == fs_new.st_ino &&
        fs_old.st_uid == fs_new.st_uid && fs_old.st_gid == fs_new.st_gid &&
        fs_old.st_rdev == fs_new.st_rdev && fs_old.st_size == fs_new.st_size);

    magic = ~msg_magic;
    atomic_puts("r: recmmsg'ing socket ...");

    breakpoint();
    test_assert(1 == recvmmsg(sock, &mmsg, 1, 0, NULL));
    atomic_printf("r:   ... recvmmsg'd 0x%x (%u bytes)\n", magic, mmsg.msg_len);
    test_assert(msg_magic == magic);
    test_assert(mmsg.msg_hdr.msg_iov == &data);

    magic = ~msg_magic;
#if defined(SYS_socketcall)
    struct recvmmsg_arg arg = { 0 };
    arg.sockfd = sock;
    arg.msgvec = &mmsg;
    arg.vlen = 1;
    test_assert(1 == syscall(SYS_socketcall, SYS_RECVMMSG, (void*)&arg));
#elif defined(SYS_recvmmsg)
    test_assert(1 == syscall(SYS_recvmmsg, sock, &mmsg, 1, 0, NULL));
#else
#error unable to call recvmmsg
#endif
    atomic_printf("r:   ... recvmmsg'd(by socketcall) 0x%x (%u bytes)\n", magic,
                  mmsg.msg_len);
    test_assert(msg_magic == magic);

    free(cmptr);
  }
  {
    struct msghdr msg = { 0 };
    struct iovec iovs[2];
    char c1 = '\0', c2 = '\0';

    iovs[0].iov_base = &c1;
    iovs[0].iov_len = sizeof(c1);
    iovs[1].iov_base = &c2;
    iovs[1].iov_len = sizeof(c2);

    msg.msg_iov = iovs;
    msg.msg_iovlen = sizeof(iovs) / sizeof(iovs[0]);

    atomic_puts("r: recmsg'ing socket with two iovs ...");
    test_assert(2 == recvmsg(sock, &msg, 0));
    atomic_printf("r:   ... recvmsg'd '%c' and '%c'\n", c1, c2);

    test_assert(c1 == token);
    token++;
    test_assert(c2 == token);
    token++;
  }
  {
    struct pollfd pfd;

    atomic_puts("r: polling socket ...");
    pfd.fd = sock;
    pfd.events = POLLIN;
    gettimeofday(&ts, NULL);
    poll(&pfd, 1, -1);
    atomic_puts("r:   ... done, doing nonblocking read ...");
    test_assert(1 == read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  {
    struct pollfd pfd;

    atomic_puts("r: polling socket ...");
    pfd.fd = sock;
    pfd.events = POLLIN;
    gettimeofday(&ts, NULL);
    ppoll(&pfd, 1, NULL, NULL);
    atomic_puts("r:   ... done, doing nonblocking read ...");
    test_assert(1 == read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  {
    fd_set fds;
    const struct timeval infinity = { 1 << 30, 0 };
    struct timeval tv = infinity;
    int ret;

    atomic_puts("r: select()ing socket ...");
    FD_ZERO(&fds);
    FD_SET(sock, &fds);
#if defined(__i386__)
    struct select_arg arg = { 0 };
    arg.n_fds = sock + 1;
    arg.read = &fds;
    arg.write = NULL;
    arg.except = NULL;
    arg.timeout = &tv;
    ret = syscall(SYS_select, &arg);
#else
    ret = syscall(SYS_select, sock + 1, &fds, NULL, NULL, &tv);
#endif
    atomic_printf("r:   ... returned %d; tv { %ld, %ld }\n", ret, tv.tv_sec,
                  tv.tv_usec);
    test_assert(1 == ret);
    test_assert(FD_ISSET(sock, &fds));
    test_assert(0 < tv.tv_sec && tv.tv_sec < infinity.tv_sec);

    atomic_puts("r:   ... done, doing nonblocking read ...");
    test_assert(1 == read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  {
    fd_set fds;
    const struct timeval infinity = { 1 << 30, 0 };
    struct timeval tv = infinity;
    int ret;

    atomic_puts("r: select()ing socket ...");
    FD_ZERO(&fds);
    FD_SET(sock, &fds);
    ret = select(sock + 1, &fds, NULL, NULL, &tv);
    atomic_printf("r:   ... returned %d; tv { %ld, %ld }\n", ret, tv.tv_sec,
                  tv.tv_usec);
    test_assert(1 == ret);
    test_assert(FD_ISSET(sock, &fds));
    test_assert(0 < tv.tv_sec && tv.tv_sec < infinity.tv_sec);

    atomic_puts("r:   ... done, doing nonblocking read ...");
    test_assert(1 == read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  {
    int epfd;
    struct epoll_event ev;

    atomic_puts("r: epolling socket ...");
    test_assert(0 <= (epfd = epoll_create(1 /*num events*/)));
    ev.events = EPOLLIN;
    ev.data.fd = sock;
    gettimeofday(&ts, NULL);
    test_assert(0 == epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev));
    test_assert(1 == epoll_wait(epfd, &ev, 1, -1));
    atomic_puts("r:   ... done, doing nonblocking read ...");
    test_assert(sock == ev.data.fd);
    test_assert(1 == epoll_wait(epfd, &ev, 1, -1));
    test_assert(1 == read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;

    close(epfd);
  }
  {
    char* buf = (char*)malloc(num_sockbuf_bytes);
    ssize_t nwritten = 0;
    struct iovec iov;

    ++token;
    memset(buf, token, num_sockbuf_bytes);

    atomic_printf("r: writing outbuf of size %zd ...\n", num_sockbuf_bytes);
    while (nwritten < num_sockbuf_bytes) {
      ssize_t this_write = write(sock, buf, num_sockbuf_bytes - nwritten);
      atomic_printf("r:   wrote %zd bytes this time\n", this_write);
      nwritten += this_write;
    }

    ++token;
    memset(buf, token, num_sockbuf_bytes);
    iov.iov_base = buf;
    iov.iov_len = num_sockbuf_bytes;
    atomic_printf("r: writev()ing outbuf of size %zd ...\n", num_sockbuf_bytes);
    while (iov.iov_len > 0) {
      ssize_t this_write = writev(sock, &iov, 1);
      atomic_printf("r:   wrote %zd bytes this time\n", this_write);
      iov.iov_len -= this_write;
    }

    free(buf);
  }

  atomic_puts("r: reading socket with masked signals ...");
  {
    sigset_t old_mask, mask;
    sigfillset(&mask);
    test_assert(0 == pthread_sigmask(SIG_BLOCK, &mask, &old_mask));

    test_assert(1 == read(sock, &c, sizeof(c)));

    test_assert(0 == pthread_sigmask(SIG_SETMASK, &old_mask, NULL));
  }
  ++token;
  atomic_printf("r:   ... read '%c'\n", c);
  test_assert(c == token);

  /* Make the main thread wait on our join() */
  atomic_puts("r: sleeping ...");
  usleep(500000);

  return NULL;
}
Beispiel #21
0
int CNIOLinux_recvmmsg(int sockfd, CNIOLinux_mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout) {
    // This is technically undefined behaviour, but it's basically fine because these types are the same size, and we
    // don't think the compiler is inclined to blow anything up here.
    return recvmmsg(sockfd, (struct mmsghdr *)msgvec, vlen, flags, timeout);
}
Beispiel #22
0
int main()
{
    int s, fd_null;
    struct sockaddr_in sin1, sin2, sin4, from;
    pid_t pid = 0;
    char buf[2][1024];
    fd_set rdfds;
    struct timeval timeout;
    socklen_t fromlen;
    struct mmsghdr msgs[2];
    struct iovec iov[2];
    struct sockaddr_un sun1;
    char tmpsunpath[1024];
    struct timespec tim = {0, 20000};

    /* initialize sockaddr's */
    sin1.sin_family = AF_INET;
    sin1.sin_port = htons((getpid() % 32768) + 11000);
    sin1.sin_addr.s_addr = INADDR_ANY;

    (void)strcpy(tmpsunpath, "udsockXXXXXX");
    s = mkstemp(tmpsunpath);
    close(s);
    unlink(tmpsunpath);
    sun1.sun_family = AF_UNIX;
    strcpy(sun1.sun_path, tmpsunpath);

    pid = start_server(&sin1, &sun1);

    sin2.sin_family = AF_INET;
    /* this port must be unused! */
    sin2.sin_port = htons((getpid() % 32768) + 10000);
    sin2.sin_addr.s_addr = INADDR_ANY;

    sin4.sin_family = 47;	/* bogus address family */
    sin4.sin_port = 0;
    sin4.sin_addr.s_addr = htonl(0x0AFFFEFD);
    fromlen = sizeof(from);

    memset(msgs, 0, sizeof(msgs));
    iov[0].iov_base = buf[0];
    iov[0].iov_len = sizeof(buf[0]);
    msgs[0].msg_hdr.msg_iov = &iov[0];
    msgs[0].msg_hdr.msg_iovlen = 1;
    iov[1].iov_base = buf[1];
    iov[1].iov_len = sizeof(buf[1]);
    msgs[1].msg_hdr.msg_iov = &iov[1];
    msgs[1].msg_hdr.msg_iovlen = 1;

    fd_null = open("/dev/null", O_WRONLY);
    //staptest// [[[[open (!!!!openat (AT_FDCWD, ]]]]"/dev/null", O_WRONLY) = NNNN

    recvmmsg(-1, msgs, 2, 0, NULL);
    //staptest// recvmmsg (-1, XXXX, 2, 0x0, NULL) = -NNNN (EBADF)

    recvmmsg(fd_null, msgs, 2, MSG_DONTWAIT, NULL);
    //staptest// recvmmsg (NNNN, XXXX, 2, MSG_DONTWAIT, NULL) = -NNNN (ENOTSOCK)

    s = socket(PF_INET, SOCK_STREAM, 0);
    //staptest// socket (PF_INET, SOCK_STREAM, IPPROTO_IP) = NNNN

    connect(s, (struct sockaddr *)&sin1, sizeof(sin1));
    //staptest// connect (NNNN, {AF_INET, 0.0.0.0, NNNN}, 16) = 0

    /* Wait for something to be readable */
    FD_ZERO(&rdfds);
    FD_SET(s, &rdfds);
    timeout.tv_sec = 2;
    timeout.tv_usec = 0;
    select(s + 1, &rdfds, 0, 0, &timeout);
    //staptest// [[[[select (NNNN, XXXX, 0x[0]+, 0x[0]+, [2\.[0]+]!!!!pselect6 (NNNN, XXXX, 0x[0]+, 0x[0]+, [2\.[0]+], 0x0]]]]) = 1

    recvmmsg(s, (struct mmsghdr *)-1, 2, 0, NULL);
#ifdef __s390__
    //staptest// recvmmsg (NNNN, 0x[7]?[f]+, 2, 0x0, NULL) = -NNNN (EFAULT)
#else
    //staptest// recvmmsg (NNNN, 0x[f]+, 2, 0x0, NULL) = -NNNN (EFAULT)
#endif

    close(s);
    //staptest// close (NNNN) = 0

    s = socket(PF_INET, SOCK_STREAM, 0);
    //staptest// socket (PF_INET, SOCK_STREAM, IPPROTO_IP) = NNNN

    connect(s, (struct sockaddr *)&sin1, sizeof(sin1));
    //staptest// connect (NNNN, {AF_INET, 0.0.0.0, NNNN}, 16) = 0

    /* Wait for something to be readable */
    FD_ZERO(&rdfds);
    FD_SET(s, &rdfds);
    timeout.tv_sec = 2;
    timeout.tv_usec = 0;
    select(s + 1, &rdfds, 0, 0, &timeout);
    //staptest// [[[[select (NNNN, XXXX, 0x[0]+, 0x[0]+, [2\.[0]+]!!!!pselect6 (NNNN, XXXX, 0x[0]+, 0x[0]+, [2\.[0]+], 0x0]]]]) = 1

    // Note that the exact failure return value can differ here, so
    // we'll just ignore it. Also note that on a 32-bit kernel (i686
    // for instance), MAXSTRINGLEN is only 256. Passing a -1 as the
    // flags value can produce a string that will cause argstr to get
    // too big. So, we'll make the end of the argument optional.
    recvmmsg(s, msgs, 2, -1, NULL);
    //staptest// recvmmsg (NNNN, XXXX, 2, MSG_[^ ]+[[[[|XXXX, NULL]]]]?) = -NNNN

    close(s);
    //staptest// close (NNNN) = 0

    s = socket(PF_UNIX, SOCK_STREAM, 0);
    //staptest// socket (PF_LOCAL, SOCK_STREAM, 0) = NNNN

    connect(s, (struct sockaddr *)&sun1, sizeof(sun1));
    //staptest// connect (NNNN, {AF_UNIX, "[^"]+"}, 110) = 0

    // We don't want to wait for -1 vectors, since we'd be waiting for
    // a long time...
    recvmmsg(s, msgs, -1, MSG_DONTWAIT, NULL);
    //staptest// recvmmsg (NNNN, XXXX, 4294967295, MSG_DONTWAIT, NULL) = -NNNN (EAGAIN)

    recvmmsg(s, msgs, 2, MSG_DONTWAIT, (struct timespec *)-1);
#ifdef __s390__
    //staptest// recvmmsg (NNNN, XXXX, 2, MSG_DONTWAIT, 0x[7]?[f]+) = -NNNN (EFAULT)
#else
    //staptest// recvmmsg (NNNN, XXXX, 2, MSG_DONTWAIT, 0x[f]+) = -NNNN (EFAULT)
#endif

    close(s);
    //staptest// close (NNNN) = 0

    s = socket(PF_UNIX, SOCK_STREAM, 0);
    //staptest// socket (PF_LOCAL, SOCK_STREAM, 0) = NNNN

    connect(s, (struct sockaddr *)&sun1, sizeof(sun1));
    //staptest// connect (NNNN, {AF_UNIX, "[^"]+"}, 110) = 0

    write(s, "R", 1);
    //staptest// write (NNNN, "R", 1) = 1

    /* Wait for something to be readable */
    FD_ZERO(&rdfds);
    FD_SET(s, &rdfds);
    timeout.tv_sec = 2;
    timeout.tv_usec = 0;
    select(s + 1, &rdfds, 0, 0, &timeout);
    //staptest// [[[[select (NNNN, XXXX, 0x[0]+, 0x[0]+, [2\.[0]+]!!!!pselect6 (NNNN, XXXX, 0x[0]+, 0x[0]+, [2\.[0]+], 0x0]]]]) = 1

    recvmmsg(s, msgs, 2, MSG_DONTWAIT, NULL);
    //staptest// recvmmsg (NNNN, XXXX, 2, MSG_DONTWAIT, NULL) = NNNN

    close(s);
    //staptest// close (NNNN) = 0

    s = socket(PF_UNIX, SOCK_STREAM, 0);
    //staptest// socket (PF_LOCAL, SOCK_STREAM, 0) = NNNN

    connect(s, (struct sockaddr *)&sun1, sizeof(sun1));
    //staptest// connect (NNNN, {AF_UNIX, "[^"]+"}, 110) = 0

    write(s, "R", 1);
    //staptest// write (NNNN, "R", 1) = 1

    /* Wait for something to be readable */
    FD_ZERO(&rdfds);
    FD_SET(s, &rdfds);
    timeout.tv_sec = 2;
    timeout.tv_usec = 0;
    select(s + 1, &rdfds, 0, 0, &timeout);
    //staptest// [[[[select (NNNN, XXXX, 0x[0]+, 0x[0]+, [2\.[0]+]!!!!pselect6 (NNNN, XXXX, 0x[0]+, 0x[0]+, [2\.[0]+], 0x0]]]]) = 1

    recvmmsg(s, msgs, 2, MSG_DONTWAIT, &tim);
    //staptest// recvmmsg (NNNN, XXXX, 2, MSG_DONTWAIT, \[0.000020000\]) = NNNN

    close(s);
    //staptest// close (NNNN) = 0

    close(fd_null);
    //staptest// close (NNNN) = 0

    if (pid > 0)
	(void)kill(pid, SIGKILL);	/* kill server */
    //staptest// kill (NNNN, SIGKILL) = 0

    (void)unlink(tmpsunpath);

    return 0;
}
Beispiel #23
0
static void statsd_run_recvmmsg(struct brubeck_statsd *statsd, int sock)
{
	const unsigned int SIM_PACKETS = statsd->mmsg_count;
	struct brubeck_server *server = statsd->sampler.server;

	struct brubeck_statsd_msg msg;
	struct brubeck_metric *metric;
	unsigned int i;

	struct iovec iovecs[SIM_PACKETS];
	struct mmsghdr msgs[SIM_PACKETS];

	memset(msgs, 0x0, sizeof(msgs));

	for (i = 0; i < SIM_PACKETS; ++i) {
		iovecs[i].iov_base = xmalloc(MAX_PACKET_SIZE);
		iovecs[i].iov_len = MAX_PACKET_SIZE - 1;
		msgs[i].msg_hdr.msg_iov = &iovecs[i];
		msgs[i].msg_hdr.msg_iovlen = 1;
	}

	log_splunk("sampler=statsd event=worker_online syscall=recvmmsg socket=%d", sock);

	for (;;) {
		int res = recvmmsg(sock, msgs, SIM_PACKETS, 0, NULL);

		if (res < 0) {
			if (errno == EAGAIN || errno == EINTR)
				continue;

			log_splunk_errno("sampler=statsd event=failed_read");
			brubeck_server_mark_dropped(server);
			continue;
		}

		/* store stats */
		brubeck_atomic_add(&server->stats.metrics, SIM_PACKETS);
		brubeck_atomic_add(&statsd->sampler.inflow, SIM_PACKETS);

		for (i = 0; i < SIM_PACKETS; ++i) {
			char *buf = msgs[i].msg_hdr.msg_iov->iov_base;
			int len = msgs[i].msg_len;

            char *cur;
            int curLen;

            int processed = 0;

            do {
                cur = memchr(buf,'\n', len);
                if(cur == NULL){
                    cur = buf;
                    curLen = len - processed;
                }
                else{
                    curLen = cur - buf;
                    cur = buf;
                }

                //log_splunk("msg to be processed ='%.*s'", curLen, cur);
                if (brubeck_statsd_msg_parse(&msg, cur, curLen) < 0) {
                    if (msg.key_len > 0)
                        buf[msg.key_len] = ':';

                    log_splunk("sampler=statsd event=bad_key key='%.*s'", curLen, cur);

                    brubeck_server_mark_dropped(server);
                    continue;
                }

                //log_splunk("key: %s, value: %s",msg.key, msg.value);

                metric = brubeck_metric_find(server, msg.key, msg.key_len, msg.type);
                if (metric != NULL)
                    brubeck_metric_record(metric, msg.value);

                processed += curLen +1;
                buf += curLen +1;
            }while(processed < len);
		}
	}
}