Пример #1
0
/* Notify the listener that the client has finished sending a message, and
 * transfer all details for handling the response to it. Blocking. */
static bool enqueue_EXPECT_message_to_listener(bus *b, boxed_msg *box) {
    /* Notify listener that it should expect a response to a
     * successfully sent message. */
    BUS_LOG_SNPRINTF(b, 3, LOG_SENDER, b->udata, 128,
        "telling listener to EXPECT sent response, with box %p, seq_id %lld",
        (void *)box, (long long)box->out_seq_id);
    
    if (box->result.status == BUS_SEND_UNDEFINED) {
        box->result.status = BUS_SEND_REQUEST_COMPLETE;
    }

    struct listener *l = Bus_GetListenerForSocket(b, box->fd);

    for (int retries = 0; retries < SEND_NOTIFY_LISTENER_RETRIES; retries++) {
        #ifndef TEST
        uint16_t backpressure = 0;
        #endif
        /* If this succeeds, then this thread cannot touch the box anymore. */
        if (Listener_ExpectResponse(l, box, &backpressure)) {
            Bus_BackpressureDelay(b, backpressure,
                LISTENER_EXPECT_BACKPRESSURE_SHIFT);
            return true;
        } else {
            BUS_LOG_SNPRINTF(b, 5, LOG_SENDER, b->udata, 64,
                "enqueue_request_sent: failed delivery %d", retries);
            syscall_poll(NULL, 0, SEND_NOTIFY_LISTENER_RETRY_DELAY);
        }
    }

    /* Timeout, will be treated as a TX error */
    return false;
}
Пример #2
0
int io_poll(int64_t *remain, int64_t *timeout)
{
  int to = -1;
  uint64_t old;
  uint64_t deadline = timer_mtime;
  size_t i;
  int ret;

  old = timer_mtime;

  /* There is a timeout, set it */
  if(timeout) if(*timeout >= 0LL)
  {
    to = (int)(*timeout);
    deadline = timer_mtime + *timeout + 10;
  }

  /* Do the actual poll() */
  ret = syscall_poll(io_count ? io_pfds : NULL, io_count, to);

  /* Update system time */
  timer_update();

  /*
   * If a timeout was set then set the timeout pointer
   * to the remaining time until the poll deadline.
   */
  if(timeout && remain)
  {
    *remain = deadline - timer_mtime;

    if(*remain < 0LL)
    {
      if(*remain < -POLL_WARN_DELTA)
        log(io_log, L_warning,
            "Timing error: poll() returned too late (diff: %lli)",
            *remain);

      *remain = 0;
    }

    if(*remain > *timeout)
    {
      if(*remain > *timeout + POLL_WARN_DELTA)
        log(io_log, L_warning,
            "Timing error: poll() returned too early (diff: %lli)",
            *remain);

      *remain = *timeout;
    }
  }

  /* Now set the returned events */
  for(i = 0; i < io_count; i++)
    io_set_revents(io_pfds[i].fd);

  return ret;
}
Пример #3
0
static bool do_blocking_connection(struct bus *b, SSL *ssl, int fd) {
    BUS_LOG_SNPRINTF(b, 2, LOG_SOCKET_REGISTERED, b->udata, 128,
        "SSL_Connect handshake for socket %d", fd);

    struct pollfd fds[1];
    fds[0].fd = fd;
    fds[0].events = POLLOUT;
    
    bool connected = false;
    size_t elapsed = 0;

    while (!connected) {
        int pres = syscall_poll(fds, 1, TIMEOUT_MSEC);
        BUS_LOG_SNPRINTF(b, 5, LOG_SOCKET_REGISTERED, b->udata, 128,
            "SSL_Connect handshake for socket %d, poll res %d", fd, pres);

        if (pres < 0) {
            if (Util_IsResumableIOError(errno)) {
                errno = 0;
            } else {
                /*  */
                assert(false);
            }
        } else if (pres > 0) {
            if (fds[0].revents & (POLLOUT | POLLIN)) {
                int connect_res = SSL_connect(ssl);
                BUS_LOG_SNPRINTF(b, 5, LOG_SOCKET_REGISTERED, b->udata, 128,
                    "socket %d: connect_res %d", fd, connect_res);

                if (connect_res == 1) {
                    BUS_LOG_SNPRINTF(b, 5, LOG_SOCKET_REGISTERED, b->udata, 128,
                        "socket %d: successfully connected", fd);
                    connected = true;
                } else if (connect_res < 0) {
                    int reason = SSL_get_error(ssl, connect_res);

                    switch (reason) {
                    case SSL_ERROR_WANT_WRITE:
                        BUS_LOG(b, 4, LOG_SOCKET_REGISTERED, "WANT_WRITE", b->udata);
                        fds[0].events = POLLOUT;
                        break;
                        
                    case SSL_ERROR_WANT_READ:
                        BUS_LOG(b, 4, LOG_SOCKET_REGISTERED, "WANT_READ", b->udata);
                        fds[0].events = POLLIN;
                        break;
                        
                    case SSL_ERROR_SYSCALL:
                    {
                        if (Util_IsResumableIOError(errno)) {
                            errno = 0;
                            break;
                        } else {
                            unsigned long errval = ERR_get_error();
                            char ebuf[256];
                            BUS_LOG_SNPRINTF(b, 1, LOG_SOCKET_REGISTERED, b->udata, 128,
                                "socket %d: ERROR -- %s", fd, ERR_error_string(errval, ebuf));
                        }
                    }
                    break;
                    default:
                    {
                        unsigned long errval = ERR_get_error();
                        char ebuf[256];
                        BUS_LOG_SNPRINTF(b, 1, LOG_SOCKET_REGISTERED, b->udata, 128,
                            "socket %d: ERROR %d -- %s", fd, reason, ERR_error_string(errval, ebuf));
                        assert(false);
                    }
                    }

                } else {
                    BUS_LOG_SNPRINTF(b, 5, LOG_SOCKET_REGISTERED, b->udata, 128,
                        "socket %d: unknown state, setting event bask to (POLLIN | POLLOUT)",
                        fd);
                    fds[0].events = (POLLIN | POLLOUT);
                }
            } else if (fds[0].revents & POLLHUP) {
                BUS_LOG_SNPRINTF(b, 1, LOG_SOCKET_REGISTERED, b->udata, 128,
                    "SSL_Connect: HUP on %d", fd);
                return false;
            } else if (fds[0].revents & POLLERR) {
                BUS_LOG_SNPRINTF(b,12, LOG_SOCKET_REGISTERED, b->udata, 128,
                    "SSL_Connect: ERR on %d", fd);
                return false;
            }
        } else {
            BUS_LOG(b, 4, LOG_SOCKET_REGISTERED, "poll timeout", b->udata);
            elapsed += TIMEOUT_MSEC;
            if (elapsed > MAX_TIMEOUT) {
                BUS_LOG(b, 2, LOG_SOCKET_REGISTERED, "timed out", b->udata);
                return false;
            }
        }
    }
    
    return connected;
}
Пример #4
0
bool BusPoll_OnCompletion(struct bus *b, int fd) {
    /* POLL in a pipe */
    #ifndef TEST
    struct pollfd fds[1];
    #endif
    fds[0].fd = fd;
    fds[0].events = POLLIN;

    for (;;) {
        BUS_LOG(b, 5, LOG_SENDING_REQUEST, "Polling on completion...tick...", b->udata);
        #ifdef TEST
        errno = poll_errno;
        #endif
        BUS_LOG_SNPRINTF(b, 5, LOG_SENDING_REQUEST, b->udata, 64,
            "poll_on_completion, polling %d", fd);
        int res = syscall_poll(fds, 1, -1);
        BUS_LOG_SNPRINTF(b, 5, LOG_SENDING_REQUEST, b->udata, 64,
            "poll_on_completion for %d, res %d (errno %d)", fd, res, errno);
        if (res == -1) {
            if (Util_IsResumableIOError(errno)) {
                BUS_LOG_SNPRINTF(b, 5, LOG_SENDING_REQUEST, b->udata, 64,
                    "poll_on_completion, resumable IO error %d", errno);
                errno = 0;
                continue;
            } else {
                BUS_LOG_SNPRINTF(b, 1, LOG_SENDING_REQUEST, b->udata, 64,
                    "poll_on_completion, non-resumable IO error %d", errno);
                return false;
            }
        } else if (res == 1) {
            uint16_t msec = 0;
            #ifndef TEST
            uint8_t read_buf[sizeof(uint8_t) + sizeof(uint16_t)];
            #endif

            if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
                BUS_LOG(b, 1, LOG_SENDING_REQUEST, "failed (broken alert pipe)", b->udata);
                return false;
            }

            BUS_LOG(b, 3, LOG_SENDING_REQUEST, "Reading alert pipe...", b->udata);
            #ifdef TEST
            errno = read_errno;
            #endif
            ssize_t sz = syscall_read(fd, read_buf, sizeof(read_buf));

            if (sz == sizeof(read_buf)) {
                /* Payload: little-endian uint16_t, msec of backpressure. */
                assert(read_buf[0] == LISTENER_MSG_TAG);

                msec = (read_buf[1] << 0) + (read_buf[2] << 8);
                Bus_BackpressureDelay(b, msec, LISTENER_BACKPRESSURE_SHIFT);
                BUS_LOG(b, 4, LOG_SENDING_REQUEST, "sent!", b->udata);
                return true;
            } else if (sz == -1) {
                if (Util_IsResumableIOError(errno)) {
                    BUS_LOG_SNPRINTF(b, 5, LOG_SENDING_REQUEST, b->udata, 64,
                        "poll_on_completion read, resumable IO error %d", errno);
                    errno = 0;
                    continue;
                } else {
                    BUS_LOG_SNPRINTF(b, 2, LOG_SENDING_REQUEST, b->udata, 64,
                        "poll_on_completion read, non-resumable IO error %d", errno);
                    errno = 0;
                    return false;
                }
            } else {
                BUS_LOG_SNPRINTF(b, 1, LOG_SENDING_REQUEST, b->udata, 64,
                    "poll_on_completion bad read size %zd", sz);
                return false;
            }
        } else {
            /* This should never happen, but I have seen it occur on OSX.
             * If we log it, reset errno, and continue, it does not appear
             * to fall into busywaiting by always returning 0. */
            BUS_LOG_SNPRINTF(b, 1, LOG_SENDING_REQUEST, b->udata, 64,
                "poll_on_completion, blocking forever returned %d, errno %d", res, errno);
            errno = 0;
        }
    }
}
Пример #5
0
/** @brief Handles all syscalls of the tracked pid until it does a blocking action.
 *
 *  Blocking actions are stuff that must be reported to the simulator and which
 *  completion takes time. The most prominent examples are related to sending and
 *  receiving data.
 *
 *  The tracked pid can run more than one syscall in this function if theses calls
 *  are about the metadata that we maintain in simterpose without exposing them to
 *  simgrid. For example, if you call socket() or accept(), we only have to maintain
 *  our metadata but there is no need to inform the simulator, nor to ask for the
 *  completion time of these things.
 */
int process_handle(process_descriptor_t * proc)
{
  reg_s arg;
  pid_t pid = proc->pid;
  XBT_DEBUG("PROCESS HANDLE MSG");
  while (1) {
    ptrace_get_register(pid, &arg);
    int ret;
    XBT_DEBUG("found syscall: [%d] %s (%ld) = %ld, in_syscall = %d", pid, syscall_list[arg.reg_orig], arg.reg_orig,
	      arg.ret, proc->in_syscall);

    switch (arg.reg_orig) {
    case SYS_creat:
      syscall_creat(&arg, proc);
      break;

    case SYS_open:
      XBT_DEBUG("On open");
      XBT_DEBUG("Valeur des registres dans l'AS:");
      XBT_DEBUG("Valeur de retour %lu", arg.ret);
      XBT_DEBUG("Valeur des arg %lu %lu %lu %lu %lu %lu", arg.arg[0], arg.arg[1], arg.arg[2], arg.arg[3], arg.arg[4], arg.arg[5]);
      syscall_open(&arg, proc);
      break;

    case SYS_close:
      syscall_close(&arg, proc);
      break;

    case SYS_read:
      syscall_read(&arg, proc);
      break;

    case SYS_write:
      XBT_DEBUG("On write");
      XBT_DEBUG("Valeur des registres dans l'AS:");
      XBT_DEBUG("Valeur de retour %lu", arg.ret);
      XBT_DEBUG("Valeur des arg %lu %lu %lu %lu %lu %lu", arg.arg[0], arg.arg[1], arg.arg[2], arg.arg[3], arg.arg[4], arg.arg[5]);
      if ((ret = syscall_write(&arg, proc)))
	return ret;
      break;

    case SYS_dup:
      syscall_dup(&arg, proc);
      break;

    case SYS_dup2:
      syscall_dup2(&arg, proc);
      break;

    case SYS_fcntl:
      syscall_fcntl(&arg, proc);
      break;

    case SYS_lseek:
      syscall_lseek(&arg, proc);
      break;

    case SYS_poll:
      syscall_poll(&arg, proc);
      break;

    case SYS_select:
      syscall_select(&arg, proc);
      break;

    case SYS_pipe:
      syscall_pipe(&arg, proc);

    case SYS_brk:
      syscall_brk(&arg, proc);
      break;

    case SYS_socket:
      syscall_socket(&arg, proc);
      break;

    case SYS_connect:
      syscall_connect(&arg, proc);
      break;

    case SYS_bind:
      syscall_bind(&arg, proc);
      break;

    case SYS_listen:
      syscall_listen(&arg, proc);
      break;

    case SYS_accept:
      syscall_accept(&arg, proc);
      break;

#if UINTPTR_MAX == 0xffffffff
      /* 32-bit architecture */
    case SYS_send:
      ret = syscall_send(&arg, proc);
      if (ret)
	return ret;
      break;

    case SYS_recv:
      syscall_recv(&arg, proc);
      break;
#endif

    case SYS_sendto:
      ret = syscall_sendto(&arg, proc);
      if (ret)
        return ret;
      break;

    case SYS_recvfrom:
      syscall_recvfrom(&arg, proc);
      break;

    case SYS_sendmsg:
      if ((ret = syscall_sendmsg( &arg, proc)))
        return ret;
      break;

    case SYS_recvmsg:
      syscall_recvmsg(&arg, proc);
      break;

    case SYS_shutdown:
      syscall_shutdown(&arg, proc);
      break;

    case SYS_getpeername:
      syscall_getpeername(&arg, proc);
      break;

    case SYS_getsockopt:
      syscall_getsockopt(&arg, proc);
      break;

    case SYS_setsockopt:
      syscall_setsockopt(&arg, proc);
      break;

    case SYS_clone:
      syscall_clone(&arg, proc);
      break;

    case SYS_execve:
      syscall_execve(&arg, proc);
      break;

    case SYS_exit:
      XBT_DEBUG("exit(%ld) called", arg.arg[0]);
      return syscall_exit(&arg, proc);
      break;

    case SYS_exit_group:
      XBT_DEBUG("exit_group(%ld) called", arg.arg[0]);
      return syscall_exit(&arg, proc);
      break;

    case SYS_getpid:
      syscall_getpid(&arg, proc);
      break;

    case SYS_tuxcall:
      syscall_tuxcall(&arg, proc);
      break;

    default:
      syscall_default(pid, &arg, proc);
      break;
    }

      // Step the traced process
      ptrace_resume_process(pid);
      // XBT_DEBUG("process resumed, waitpid");
      waitpid(pid, &(proc->status), __WALL);
    }                             // while(1)

      THROW_IMPOSSIBLE;             //There's no way to quit the loop
      return 0;
    }