Exemplo n.º 1
0
/* static void comm_connect_tryconnect(int fd, void *notused)
 * Input: The fd, the handler data(unused).
 * Output: None.
 * Side-effects: Try and connect with pending connect data for the FD. If
 *               we succeed or get a fatal error, call the callback.
 *               Otherwise, it is still blocking or something, so register
 *               to select for a write event on this FD.
 */
static void
comm_connect_tryconnect(int fd, void *notused)
{
	int retval;
	fde_t *F = &fd_table[fd];

	if(F->connect.callback == NULL)
		return;
	/* Try the connect() */
	retval = connect(fd,
			 (struct sockaddr *) &fd_table[fd].connect.hostaddr, 
						       GET_SS_LEN(fd_table[fd].connect.hostaddr));
	/* Error? */
	if(retval < 0)
	{
		/*
		 * If we get EISCONN, then we've already connect()ed the socket,
		 * which is a good thing.
		 *   -- adrian
		 */
		if(errno == EISCONN)
			comm_connect_callback(F->fd, COMM_OK);
		else if(ignoreErrno(errno))
			/* Ignore error? Reschedule */
			comm_setselect(F->fd, FDLIST_SERVER, COMM_SELECT_WRITE|COMM_SELECT_RETRY,
				       comm_connect_tryconnect, NULL, 0);
		else
			/* Error? Fail with COMM_ERR_CONNECT */
			comm_connect_callback(F->fd, COMM_ERR_CONNECT);
		return;
	}
	/* If we get here, we've suceeded, so call with COMM_OK */
	comm_connect_callback(F->fd, COMM_OK);
}
Exemplo n.º 2
0
/* Read from client side and queue it for writing to the server */
static void
sslReadClient(int fd, void *data)
{
    SslStateData *sslState = data;
    int len;
    assert(fd == sslState->client.fd);
    debug(26, 3) ("sslReadClient: FD %d, reading %d bytes at offset %d\n",
	fd, SQUID_TCP_SO_RCVBUF - sslState->client.len,
	sslState->client.len);
    Counter.syscalls.sock.reads++;
    len = read(fd,
	sslState->client.buf + sslState->client.len,
	SQUID_TCP_SO_RCVBUF - sslState->client.len);
    debug(26, 3) ("sslReadClient: FD %d, read   %d bytes\n", fd, len);
    if (len > 0) {
	fd_bytes(fd, len, FD_READ);
	kb_incr(&Counter.client_http.kbytes_in, len);
	sslState->client.len += len;
    }
    cbdataLock(sslState);
    if (len < 0) {
	debug(50, ECONNRESET == errno ? 3 : 1) ("sslReadClient: FD %d: read failure: %s\n",
	    fd, xstrerror());
	if (!ignoreErrno(errno))
	    comm_close(fd);
    } else if (len == 0) {
	comm_close(fd);
    }
    if (cbdataValid(sslState))
	sslSetSelect(sslState);
    cbdataUnlock(sslState);
}
Exemplo n.º 3
0
static int
do_comm_select(int msec)
{
    int i;
    int num, saved_errno;

    if (epoll_fds == 0) {
	assert(shutting_down);
	return COMM_SHUTDOWN;
    }
    statCounter.syscalls.polls++;
    num = epoll_wait(kdpfd, events, MAX_EVENTS, msec);
    saved_errno = errno;
    getCurrentTime();
    debug(5, 5) ("do_comm_select: %d fds ready\n", num);
    if (num < 0) {
	if (ignoreErrno(saved_errno))
	    return COMM_OK;

	debug(5, 1) ("comm_select: epoll failure: %s\n", xstrerror());
	return COMM_ERROR;
    }
    statHistCount(&statCounter.select_fds_hist, num);

    if (num == 0)
	return COMM_TIMEOUT;

    for (i = 0; i < num; i++) {
	comm_call_handlers(events[i].data.fd, events[i].events & ~EPOLLOUT, events[i].events & ~EPOLLIN);
    }

    return COMM_OK;
}
Exemplo n.º 4
0
static int
comm_accept_un(int fd)
{
	int sock;
	struct sockaddr_un P;
	socklen_t Slen;
	Slen = sizeof(P);
	statCounter.syscalls.sock.accepts++;
	if ((sock = accept(fd, (struct sockaddr *) &P, &Slen)) < 0)
	{
		if (ignoreErrno(errno) || errno == ECONNREFUSED || errno == ECONNABORTED)
		{
			debug(191, 5) ("comm_accept_un: FD %d: %s\n", fd, xstrerror());
			return COMM_NOMESSAGE;
		}
		else if (ENFILE == errno || EMFILE == errno)
		{
			debug(191, 3) ("comm_accept_un: FD %d: %s\n", fd, xstrerror());
			return COMM_ERROR;
		}
		else
		{
			debug(191, 1) ("comm_accept_un: FD %d: %s\n", fd, xstrerror());
			return COMM_ERROR;
		}
	}
	commSetCloseOnExec(sock);
	/* fdstat update */
	fd_open(sock, FD_SOCKET, "LSCS Request");
	commSetNonBlocking(sock);
	return sock;
}
Exemplo n.º 5
0
static void
idnsReadTcp(int fd, void *data)
{
    ssize_t n;
    idns_query *q = data;
    int ns = (q->nsends - 1) % nns;
    if (!q->tcp_buffer)
	q->tcp_buffer = memAllocBuf(1024, &q->tcp_buffer_size);
    statCounter.syscalls.sock.reads++;
    n = FD_READ_METHOD(q->tcp_socket, q->tcp_buffer + q->tcp_buffer_offset, q->tcp_buffer_size - q->tcp_buffer_offset);
    if (n < 0 && ignoreErrno(errno)) {
	commSetSelect(q->tcp_socket, COMM_SELECT_READ, idnsReadTcp, q, 0);
	return;
    }
    if (n <= 0) {
	debug(78, 1) ("idnsReadTcp: Short response from nameserver %d for %s.\n", ns + 1, q->name);
	idnsTcpCleanup(q);
	return;
    }
    fd_bytes(fd, n, FD_READ);
    q->tcp_buffer_offset += n;
    if (q->tcp_buffer_offset > 2) {
	unsigned short response_size = ntohs(*(short *) q->tcp_buffer);
	if (q->tcp_buffer_offset >= response_size + 2) {
	    nameservers[ns].nreplies++;
	    idnsGrokReply(q->tcp_buffer + 2, response_size);
	    return;
	}
	if (q->tcp_buffer_size < response_size + 2)
	    q->tcp_buffer = memReallocBuf(q->tcp_buffer, response_size + 2, &q->tcp_buffer_size);
    }
    commSetSelect(q->tcp_socket, COMM_SELECT_READ, idnsReadTcp, q, 0);
}
static int
do_comm_select(int msec)
{
    int i;
    int num;
    int fd;
    struct epoll_event *cevents;

    if (epoll_fds == 0) {
	assert(shutting_down);
	return COMM_SHUTDOWN;
    }
    statCounter.syscalls.polls++;
    num = epoll_wait(kdpfd, events, MAX_EVENTS, msec);
    if (num < 0) {
	getCurrentTime();
	if (ignoreErrno(errno))
	    return COMM_OK;

	debug(5, 1) ("comm_select: epoll failure: %s\n", xstrerror());
	return COMM_ERROR;
    }
    statHistCount(&statCounter.select_fds_hist, num);

    if (num == 0)
	return COMM_TIMEOUT;

    for (i = 0, cevents = events; i < num; i++, cevents++) {
	fd = cevents->data.fd;
	comm_call_handlers(fd, cevents->events & ~EPOLLOUT, cevents->events & ~EPOLLIN);
    }

    return COMM_OK;
}
Exemplo n.º 7
0
void
comm_select(unsigned long delay)
{
  int num, i, fd;
  static struct kevent ke[KE_LENGTH];
  struct timespec poll_time;
  PF *hdl;
  fde_t *F;

  /*
   * remember we are doing NANOseconds here, not micro/milli. God knows
   * why jlemon used a timespec, but hey, he wrote the interface, not I
   *   -- Adrian
   */
  poll_time.tv_sec = 0;
  poll_time.tv_nsec = delay * 1000000;

  num = kevent(kq, kqlst, kqoff, ke, KE_LENGTH, &poll_time);
  kqoff = 0;
  while (num < 0 && ignoreErrno(errno))
    num = kevent(kq, kqlst, 0, ke, KE_LENGTH, &poll_time);

  set_time();

  for (i = 0; i < num; i++)
  {
    fd = (int) ke[i].ident;
    hdl = NULL;
    F = &fd_table[fd];

    if (ke[i].flags & EV_ERROR)
    {
      errno = ke[i].data;
      /* XXX error == bad! -- adrian */
      continue; /* XXX! */
    }

    switch (ke[i].filter)
    {
      case EVFILT_READ:
        if ((hdl = F->read_handler) != NULL)
        {
          F->read_handler = NULL;
          hdl(fd, F->read_data);
        }
      case EVFILT_WRITE:
        if ((hdl = F->write_handler) != NULL)
        {
          F->write_handler = NULL;
          hdl(fd, F->write_data);
        }
      default:
        /* Bad! -- adrian */
        break;
    }
  }
}
Exemplo n.º 8
0
static void
idnsRead(int fd, void *data)
{
    int *N = &incoming_sockets_accepted;
    ssize_t len;
    struct sockaddr_in from;
    socklen_t from_len;
    int max = INCOMING_DNS_MAX;
    static char rbuf[SQUID_UDP_SO_RCVBUF];
    int ns;
    while (max--) {
	from_len = sizeof(from);
	memset(&from, '\0', from_len);
	statCounter.syscalls.sock.recvfroms++;
	len = recvfrom(fd, rbuf, sizeof(rbuf), 0, (struct sockaddr *) &from, &from_len);
	if (len == 0)
	    break;
	if (len < 0) {
	    if (ignoreErrno(errno))
		break;
#ifdef _SQUID_LINUX_
	    /* Some Linux systems seem to set the FD for reading and then
	     * return ECONNREFUSED when sendto() fails and generates an ICMP
	     * port unreachable message. */
	    /* or maybe an EHOSTUNREACH "No route to host" message */
	    if (errno != ECONNREFUSED && errno != EHOSTUNREACH)
#endif
		debug(50, 1) ("idnsRead: FD %d recvfrom: %s\n",
		    fd, xstrerror());
	    break;
	}
	fd_bytes(DnsSocket, len, FD_READ);
	assert(N);
	(*N)++;
	debug(78, 3) ("idnsRead: FD %d: received %d bytes from %s.\n",
	    fd,
	    (int) len,
	    inet_ntoa(from.sin_addr));
	ns = idnsFromKnownNameserver(&from);
	if (ns >= 0) {
	    nameservers[ns].nreplies++;
	} else if (Config.onoff.ignore_unknown_nameservers) {
	    static time_t last_warning = 0;
	    if (squid_curtime - last_warning > 60) {
		debug(78, 1) ("WARNING: Reply from unknown nameserver [%s]\n",
		    inet_ntoa(from.sin_addr));
		last_warning = squid_curtime;
	    }
	    continue;
	}
	idnsGrokReply(rbuf, len);
    }
    if (lru_list.head)
	commSetSelect(DnsSocket, COMM_SELECT_READ, idnsRead, NULL, 0);
}
Exemplo n.º 9
0
/*
 * copied from httpReadReply()
 *
 * by the time this is called, the ICAP headers have already
 * been read.
 */
void
icapReadReply(int fd, void *data)
{
    IcapStateData *icap = data;
    StoreEntry *entry = icap->respmod.entry;
    const request_t *request = icap->request;
    int len;
    debug(81, 5) ("icapReadReply: FD %d: icap %p.\n", fd, data);
    if (icap->flags.no_content && !icap->flags.http_server_eof) {	//AI

	return;
    }
    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
	comm_close(fd);
	return;
    }
    errno = 0;
    statCounter.syscalls.sock.reads++;
    len = memBufRead(fd, &icap->chunk_buf);
    debug(81, 5) ("icapReadReply: FD %d: len %d.\n", fd, len);
    if (len > 0) {
	fd_bytes(fd, len, FD_READ);
	kb_incr(&statCounter.icap.all.kbytes_in, len);
	commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
	if (icap->chunk_buf.size < icap->chunk_buf.capacity) {
	    *(icap->chunk_buf.buf + icap->chunk_buf.size) = '\0';
	    debug(81, 9) ("{%s}\n", icap->chunk_buf.buf);
	}
    }
    if (len <= 0) {
	debug(81, 2) ("icapReadReply: FD %d: read failure: %s.\n",
	    fd, xstrerror());
	if (ignoreErrno(errno)) {
	    debug(81, 2) ("icapReadReply: FD %d: ignored errno\n", fd);
	    commSetSelect(fd, COMM_SELECT_READ, icapReadReply, icap, 0);
	} else if (entry->mem_obj->inmem_hi == 0) {
	    ErrorState *err;
	    debug(81, 2) ("icapReadReply: FD %d: generating error page\n", fd);
	    err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	    err->request = requestLink((request_t *) request);
	    err->xerrno = errno;
	    errorAppendEntry(entry, err);
	    comm_close(fd);
	} else {
	    debug(81, 2) ("icapReadReply: FD %d: just calling comm_close()\n",
		fd);
	    comm_close(fd);
	}
	return;
    }
    if (icapReadReply2(icap) < 0)
	comm_close(fd);
}
Exemplo n.º 10
0
/* Writes data from the server buffer to the client side */
static void
sslWriteClient(int fd, void *data)
{
    SslStateData *sslState = data;
    int len;
    assert(fd == sslState->client.fd);
    debug(26, 3) ("sslWriteClient: FD %d, %d bytes to write\n",
	fd, sslState->server.len);
    Counter.syscalls.sock.writes++;
    len = write(fd,
	sslState->server.buf,
	sslState->server.len);
    debug(26, 3) ("sslWriteClient: FD %d, %d bytes written\n", fd, len);
    if (len > 0) {
	fd_bytes(fd, len, FD_WRITE);
	kb_incr(&Counter.client_http.kbytes_out, len);
	assert(len <= sslState->server.len);
	sslState->server.len -= len;
	/* increment total object size */
	if (sslState->size_ptr)
	    *sslState->size_ptr += len;
	if (sslState->server.len > 0) {
	    /* we didn't write the whole thing */
	    xmemmove(sslState->server.buf,
		sslState->server.buf + len,
		sslState->server.len);
	}
    }
    cbdataLock(sslState);
    if (len < 0) {
	debug(50, ignoreErrno(errno) ? 3 : 1)
	    ("sslWriteClient: FD %d: write failure: %s.\n", fd, xstrerror());
	if (!ignoreErrno(errno))
	    comm_close(fd);
    }
    if (cbdataValid(sslState))
	sslSetSelect(sslState);
    cbdataUnlock(sslState);
}
Exemplo n.º 11
0
static void
whoisReadReply(int fd, void *data)
{
    WhoisState *p = data;
    StoreEntry *entry = p->entry;
    char *buf = memAllocate(MEM_4K_BUF);
    MemObject *mem = entry->mem_obj;
    int len;
    statCounter.syscalls.sock.reads++;
    len = FD_READ_METHOD(fd, buf, 4095);
    buf[len] = '\0';
    debug(75, 3) ("whoisReadReply: FD %d read %d bytes\n", fd, len);
    debug(75, 5) ("{%s}\n", buf);
    if (len > 0) {
	if (0 == mem->inmem_hi) {
	    http_reply *reply = mem->reply;
	    http_version_t version;
	    storeBuffer(entry);
	    httpBuildVersion(&version, 1, 0);
	    httpReplySetHeaders(reply, version, HTTP_OK, "Gatewaying", "text/plain", -1, -1, -2);
	    httpReplySwapOut(reply, entry);
	}
	fd_bytes(fd, len, FD_READ);
	kb_incr(&statCounter.server.all.kbytes_in, len);
	kb_incr(&statCounter.server.http.kbytes_in, len);
	storeAppend(entry, buf, len);
	storeBufferFlush(entry);
	commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read);
    } else if (len < 0) {
	debug(50, 2) ("whoisReadReply: FD %d: read failure: %s.\n",
	    fd, xstrerror());
	if (ignoreErrno(errno)) {
	    commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read);
	} else {
	    ErrorState *err;
	    err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, p->fwd->request);
	    err->xerrno = errno;
	    fwdFail(p->fwd, err);
	    comm_close(fd);
	}
    } else {
	storeTimestampsSet(entry);
	storeBufferFlush(entry);
	if (!EBIT_TEST(entry->flags, RELEASE_REQUEST))
	    storeSetPublicKey(entry);
	fwdComplete(p->fwd);
	debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry));
	comm_close(fd);
    }
    memFree(buf, MEM_4K_BUF);
}
Exemplo n.º 12
0
/* Read from server side and queue it for writing to the client */
static void
sslReadServer(int fd, void *data)
{
    SslStateData *sslState = data;
    int len;
    size_t read_sz = SQUID_TCP_SO_RCVBUF - sslState->server.len;
    assert(fd == sslState->server.fd);
    debug(26, 3) ("sslReadServer: FD %d, reading %d bytes at offset %d\n",
	fd, read_sz, sslState->server.len);
    errno = 0;
#if DELAY_POOLS
    read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz);
#endif
    Counter.syscalls.sock.reads++;
    len = read(fd, sslState->server.buf + sslState->server.len, read_sz);
    debug(26, 3) ("sslReadServer: FD %d, read   %d bytes\n", fd, len);
    if (len > 0) {
	fd_bytes(fd, len, FD_READ);
#if DELAY_POOLS
	delayBytesIn(sslState->delay_id, len);
#endif
	kb_incr(&Counter.server.all.kbytes_in, len);
	kb_incr(&Counter.server.other.kbytes_in, len);
	sslState->server.len += len;
    }
    cbdataLock(sslState);
    if (len < 0) {
	debug(50, ignoreErrno(errno) ? 3 : 1)
	    ("sslReadServer: FD %d: read failure: %s\n", fd, xstrerror());
	if (!ignoreErrno(errno))
	    comm_close(fd);
    } else if (len == 0) {
	comm_close(sslState->server.fd);
    }
    if (cbdataValid(sslState))
	sslSetSelect(sslState);
    cbdataUnlock(sslState);
}
Exemplo n.º 13
0
Arquivo: disk.c Projeto: selecli/squid
/* Read from FD */
static void
diskHandleRead(int fd, void *data)
{
	dread_ctrl *ctrl_dat = data;
	fde *F = &fd_table[fd];
	int len;
	int rc = DISK_OK;
	/*
	 * FD < 0 indicates premature close; we just have to free
	 * the state data.
	 */
	if (fd < 0)
	{
		memFree(ctrl_dat, MEM_DREAD_CTRL);
		return;
	}
	if (F->disk.offset != ctrl_dat->file_offset)
	{
		debug(6, 3) ("diskHandleRead: FD %d seeking to offset %d\n",
					 fd, (int) ctrl_dat->file_offset);
		lseek(fd, ctrl_dat->file_offset, SEEK_SET);	/* XXX ignore return? */
		statCounter.syscalls.disk.seeks++;
		F->disk.offset = ctrl_dat->file_offset;
	}
	errno = 0;
	len = FD_READ_METHOD(fd, ctrl_dat->buf, ctrl_dat->req_len);
	if (len > 0)
		F->disk.offset += len;
	statCounter.syscalls.disk.reads++;
	fd_bytes(fd, len, FD_READ);
	if (len < 0)
	{
		if (ignoreErrno(errno))
		{
			commSetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0);
			return;
		}
		debug(50, 1) ("diskHandleRead: FD %d: %s\n", fd, xstrerror());
		len = 0;
		rc = DISK_ERROR;
	}
	else if (len == 0)
	{
		rc = DISK_EOF;
	}
	if (cbdataValid(ctrl_dat->client_data))
		ctrl_dat->handler(fd, ctrl_dat->buf, len, rc, ctrl_dat->client_data);
	cbdataUnlock(ctrl_dat->client_data);
	memFree(ctrl_dat, MEM_DREAD_CTRL);
}
Exemplo n.º 14
0
/* void comm_select_fdlist(unsigned long delay)
 * Input: The maximum time to delay.
 * Output: None
 * Side-effects: Deregisters future interest in IO and calls the handlers
 *               if an event occurs for an FD.
 * Comments: Check all connections for new connections and input data
 * that is to be processed. Also check for connections with data queued
 * and whether we can write it out.
 * Called to do the new-style IO, courtesy of of squid (like most of this
 * new IO code). This routine handles the stuff we've hidden in
 * comm_setselect and fd_table[] and calls callbacks for IO ready
 * events.
 */
void
comm_select(unsigned long delay)
{
  int num, fd, ci, revents;
  PF *hdl;
  fde_t *F;
  
  /* XXX kill that +1 later ! -- adrian */
  while ((num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, delay)) < 0
         && ignoreErrno(errno))
    ;

  set_time();
 
  if (num == 0)
    return;

  /* XXX we *could* optimise by falling out after doing num fds ...
   * Currently it'd be hard to do, because pollfd_list can be changed
   * within this loop (by I/O handlers) --adx
   */
  for (ci = 0; ci < pollfd_list.maxindex + 1; ci++)
  {
    if (((revents = pollfd_list.pollfds[ci].revents) == 0) ||
        (pollfd_list.pollfds[ci].fd) == -1)
      continue;

    fd = pollfd_list.pollfds[ci].fd;
    F = &fd_table[fd];

    if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
    {
      hdl = F->read_handler;
      F->read_handler = NULL;
      poll_update_pollfds(fd, POLLRDNORM, NULL);
      if (hdl)
       hdl(fd, F->read_data);
    }
    if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
    {
      hdl = F->write_handler;
      F->write_handler = NULL;
      poll_update_pollfds(fd, POLLWRNORM, NULL);
      if (hdl)
        hdl(fd, F->write_data);
    }
  }
}
Exemplo n.º 15
0
int
comm_select(unsigned long delay)
{
	int num, i;
	static struct epoll_event pfd[EPOLL_LENGTH];

	num = epoll_wait(ep, pfd, EPOLL_LENGTH, delay);
	set_time();

	if(num < 0 && !ignoreErrno(errno))
	{
		return COMM_ERROR;
	}

	if(num == 0)
		return COMM_OK;

	for (i = 0; i < num; i++)
	{
		PF *hdl;
		fde_t *F = pfd[i].data.ptr;
		if(pfd[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR))
		{
			callbacks_called++;
			hdl = F->read_handler;
			if(hdl)
				hdl(F->fd, F->read_data);
			else
				ilog(L_WARN, "s_bsd_epoll.c: NULL read handler called");
		}

		if(F->flags.open == 0)
		{
			/* Read handler closed us..go on and do something useful */
			continue;
		}
		if(pfd[i].events & (EPOLLOUT | EPOLLHUP | EPOLLERR))
		{
			callbacks_called++;
			hdl = F->write_handler;
			if(hdl)
				hdl(F->fd, F->write_data);
			else
				ilog(L_WARN, "s_bsd_epoll.c: NULL write handler called");
		}
	}
	return COMM_OK;
}
Exemplo n.º 16
0
static int
do_comm_select(int msec)
{
    int num, saved_errno;
    struct timeval tv;
    fd_set readfds;
    fd_set writefds;
    fd_set errfds;
    int fd;

    if (nreadfds + nwritefds == 0) {
	assert(shutting_down);
	return COMM_SHUTDOWN;
    }
    memcpy(&readfds, &global_readfds, sizeof(fd_set));
    memcpy(&writefds, &global_writefds, sizeof(fd_set));
    memcpy(&errfds, &global_writefds, sizeof(fd_set));
    tv.tv_sec = msec / 1000;
    tv.tv_usec = (msec % 1000) * 1000;
    statCounter.syscalls.selects++;
    num = select(Biggest_FD + 1, &readfds, &writefds, &errfds, &tv);
    saved_errno = errno;
    getCurrentTime();
    debug(5, 5) ("do_comm_select: %d fds ready\n", num);
    if (num < 0) {
	if (ignoreErrno(saved_errno))
	    return COMM_OK;

	debug(5, 1) ("comm_select: select failure: %s\n", xstrerror());
	return COMM_ERROR;
    }
    statHistCount(&statCounter.select_fds_hist, num);

    if (num == 0)
	return COMM_TIMEOUT;

    for (fd = 0; fd <= Biggest_FD; fd++) {
	int read_event = FD_ISSET(fd, &readfds);
	int write_event = FD_ISSET(fd, &writefds) || FD_ISSET(fd, &errfds);
	if (read_event || write_event)
	    comm_call_handlers(fd, read_event, write_event);
    }
    return COMM_OK;
}
static int
do_comm_select(int msec)
{
    int num;
    int i;

    if (nfds == 0) {
	assert(shutting_down);
	return COMM_SHUTDOWN;
    }
    statCounter.syscalls.selects++;
    num = poll(pfds, nfds, msec);
    if (num < 0) {
	getCurrentTime();
	if (ignoreErrno(errno))
	    return COMM_OK;

	debug(5, 1) ("comm_select: poll failure: %s\n", xstrerror());
	return COMM_ERROR;
    }
    statHistCount(&statCounter.select_fds_hist, num);

    if (num == 0)
	return COMM_TIMEOUT;

    for (i = nfds - 1; num > 0 && i >= 0; i--) {
	struct pollfd *pfd = &pfds[i];
	short read_event, write_event;

	if (!pfd->revents)
	    continue;

	read_event = pfd->revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR);
	write_event = pfd->revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR);

	pfd->revents = 0;

	comm_call_handlers(pfd->fd, read_event, write_event);
	num--;
    }

    return COMM_OK;
}
Exemplo n.º 18
0
static void
whoisReadReply(int fd, void *data)
{
    WhoisState *p = data;
    StoreEntry *entry = p->entry;
    char *buf = memAllocate(MEM_4K_BUF);
    MemObject *mem = entry->mem_obj;
    int len;
    statCounter.syscalls.sock.reads++;
    len = FD_READ_METHOD(fd, buf, 4095);
    buf[len] = '\0';
    debug(75, 3) ("whoisReadReply: FD %d read %d bytes\n", fd, len);
    debug(75, 5) ("{%s}\n", buf);
    if (len > 0) {
	if (0 == mem->inmem_hi)
	    mem->reply->sline.status = HTTP_OK;
	fd_bytes(fd, len, FD_READ);
	kb_incr(&statCounter.server.all.kbytes_in, len);
	kb_incr(&statCounter.server.http.kbytes_in, len);
	storeAppend(entry, buf, len);
	commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read);
    } else if (len < 0) {
	debug(50, 2) ("whoisReadReply: FD %d: read failure: %s.\n",
	    fd, xstrerror());
	if (ignoreErrno(errno)) {
	    commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read);
	} else if (mem->inmem_hi == 0) {
	    ErrorState *err;
	    err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
	    err->xerrno = errno;
	    fwdFail(p->fwd, err);
	    comm_close(fd);
	} else {
	    comm_close(fd);
	}
    } else {
	fwdComplete(p->fwd);
	debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry));
	comm_close(fd);
    }
    memFree(buf, MEM_4K_BUF);
}
Exemplo n.º 19
0
static void lscsAccept(int sock, void *data)
{
        int fd = -1;
//        fde *F;
        ConnStateData *connState = NULL;
        int max = INCOMING_HTTP_MAX;
        commSetSelect(sock, COMM_SELECT_READ, lscsAccept, data, 0);
        while (max-- && !httpAcceptDefer(sock, NULL))
        {
                if ((fd = comm_accept_un(sock)) < 0)
                {
                        if (!ignoreErrno(errno))
                                debug(191, 1) ("lscsAccept: FD %d: accept failure: %s\n",
                                                          sock, xstrerror());
                        break;
                }



                commSetSelect(fd, COMM_SELECT_READ, clientRecvFd, connState, 0);
        }
}
Exemplo n.º 20
0
/* static void comm_connect_tryconnect(int fd, void *notused)
 * Input: The fd, the handler data(unused).
 * Output: None.
 * Side-effects: Try and connect with pending connect data for the FD. If
 *               we succeed or get a fatal error, call the callback.
 *               Otherwise, it is still blocking or something, so register
 *               to select for a write event on this FD.
 */
static void
comm_connect_tryconnect(fde_t *fd, void *notused)
{
  int retval;

  /* This check is needed or re-entrant s_bsd_* like sigio break it. */
  if (fd->connect.callback == NULL)
    return;

  /* Try the connect() */
  retval = connect(fd->fd, (struct sockaddr *) &fd->connect.hostaddr, 
    fd->connect.hostaddr.ss_len);

  /* Error? */
  if (retval < 0)
  {
#ifdef _WIN32
    errno = WSAGetLastError();
#endif
    /*
     * If we get EISCONN, then we've already connect()ed the socket,
     * which is a good thing.
     *   -- adrian
     */
    if (errno == EISCONN)
      comm_connect_callback(fd, COMM_OK);
    else if (ignoreErrno(errno))
      /* Ignore error? Reschedule */
      comm_setselect(fd, COMM_SELECT_WRITE, comm_connect_tryconnect,
                     NULL, 0);
    else
      /* Error? Fail with COMM_ERR_CONNECT */
      comm_connect_callback(fd, COMM_ERR_CONNECT);
    return;
  }

  /* If we get here, we've suceeded, so call with COMM_OK */
  comm_connect_callback(fd, COMM_OK);
}
Exemplo n.º 21
0
int
comm_select(unsigned long delay)
{
	int num, i;
	static struct kevent ke[KE_LENGTH];
	struct timespec poll_time;

	/*
	 * remember we are doing NANOseconds here, not micro/milli. God knows
	 * why jlemon used a timespec, but hey, he wrote the interface, not I
	 *   -- Adrian
	 */

	poll_time.tv_sec = delay / 1000;

	poll_time.tv_nsec = (delay % 1000) * 1000000;

	for (;;)
	{
		num = kevent(kq, kqlst, kqoff, ke, KE_LENGTH, &poll_time);
		kqoff = 0;

		if(num >= 0)
			break;

		if(ignoreErrno(errno))
			break;

		set_time();

		return COMM_ERROR;

		/* NOTREACHED */
	}

	set_time();

	if(num == 0)
		return COMM_OK;	/* No error.. */

	for (i = 0; i < num; i++)
	{
		int fd = (int) ke[i].ident;
		PF *hdl = NULL;
		fde_t *F = &fd_table[fd];

		if(ke[i].flags & EV_ERROR)
		{
			errno = ke[i].data;
			/* XXX error == bad! -- adrian */
			continue;	/* XXX! */
		}

		switch (ke[i].filter)
		{

		case EVFILT_READ:

			if((hdl = F->read_handler) != NULL)
			{
				F->read_handler = NULL;
				hdl(fd, F->read_data);
			}

			break;

		case EVFILT_WRITE:

			if((hdl = F->write_handler) != NULL)
			{
				F->write_handler = NULL;
				hdl(fd, F->write_data);
			}
			break;

		default:
			/* Bad! -- adrian */
			break;
		}
	}
	return COMM_OK;
}
Exemplo n.º 22
0
/* int comm_select(unsigned long delay)
 * Input: The maximum time to delay.
 * Output: Returns -1 on error, 0 on success.
 * Side-effects: Deregisters future interest in IO and calls the handlers
 *               if an event occurs for an FD.
 * Comments: Check all connections for new connections and input data
 * that is to be processed. Also check for connections with data queued
 * and whether we can write it out.
 * Called to do the new-style IO, courtesy of of squid (like most of this
 * new IO code). This routine handles the stuff we've hidden in
 * comm_setselect and fd_table[] and calls callbacks for IO ready
 * events.
 */
int comm_select(unsigned long delay)
{
    int num = 0;
    int revents = 0;
    int sig;
    int fd;
    int ci;
    PF *hdl;
    fde_t *F;
    struct siginfo si;
    struct timespec timeout;
    timeout.tv_sec = 0;
    timeout.tv_nsec = 1000000 * delay;
    for (;;)
    {
        if (!sigio_is_screwed)
        {
            if ((sig = sigtimedwait(&our_sigset, &si, &timeout)) > 0)
            {
                if (sig == SIGIO)
                {
                    ilog(L_WARN, "Kernel RT Signal queue overflowed.  Is /proc/sys/kernel/rtsig-max too small?");
                    sigio_is_screwed = 1;
                    break;
                }
                fd = si.si_fd;
                pollfd_list.pollfds[fd].revents |= si.si_band;
                revents = pollfd_list.pollfds[fd].revents;
                num++;
                F = &fd_table[fd];
                set_time();
                if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
                {
                    callbacks_called++;
                    hdl = F->read_handler;
                    F->read_handler = NULL;
                    poll_update_pollfds(fd, POLLIN, NULL);
                    if (hdl)
                        hdl(fd, F->read_data);
                }
                if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
                {
                    callbacks_called++;
                    hdl = F->write_handler;
                    F->write_handler = NULL;
                    poll_update_pollfds(fd, POLLOUT, NULL);
                    if (hdl)
                        hdl(fd, F->write_data);
                }
            } else
                break;

        } else
            break;
    }
    
    if (!sigio_is_screwed)      /* We don't need to proceed */
    {
        set_time();
        return 0;
    }
    for (;;)
    {
        if (sigio_is_screwed)
        {
            signal(sigio_signal, SIG_IGN);
            signal(sigio_signal, SIG_DFL);
            sigio_is_screwed = 0;
        }
        num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, 0);
        if (num >= 0)
            break;
        if (ignoreErrno(errno))
            continue;
        /* error! */
        set_time();
        return -1;
        /* NOTREACHED */
    }

    /* update current time again, eww.. */
    set_time();

    if (num == 0)
        return 0;
    /* XXX we *could* optimise by falling out after doing num fds ... */
    for (ci = 0; ci < pollfd_list.maxindex + 1; ci++)
    {
        if (((revents = pollfd_list.pollfds[ci].revents) == 0) ||
            (pollfd_list.pollfds[ci].fd) == -1)
            continue;
        fd = pollfd_list.pollfds[ci].fd;
        F = &fd_table[fd];
        if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
        {
            callbacks_called++;
            hdl = F->read_handler;
            F->read_handler = NULL;
            poll_update_pollfds(fd, POLLIN, NULL);
            if (hdl)
                hdl(fd, F->read_data);
        }
        if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
        {
            callbacks_called++;
            hdl = F->write_handler;
            F->write_handler = NULL;
            poll_update_pollfds(fd, POLLOUT, NULL);
            if (hdl)
                hdl(fd, F->write_data);
        }
    }
    mask_our_signal(sigio_signal);
    return 0;
}
Exemplo n.º 23
0
int
comm_select(unsigned long delay)
{
	int num, i;
	struct pollfd pollfds[POLL_LENGTH];
	struct dvpoll dopoll;

	do
	{
		for (;;)
		{
			dopoll.dp_timeout = delay;
			dopoll.dp_nfds = POLL_LENGTH;
			dopoll.dp_fds = &pollfds[0];
			num = ioctl(dpfd, DP_POLL, &dopoll);
			if(num >= 0)
				break;
			if(ignoreErrno(errno))
				break;
			set_time();
			return COMM_ERROR;
		}

		set_time();
		if(num == 0)
			continue;

		for (i = 0; i < num; i++)
		{
			int fd = dopoll.dp_fds[i].fd;
			PF *hdl = NULL;
			fde_t *F = &fd_table[fd];
			if((dopoll.dp_fds[i].revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
			   && (dopoll.dp_fds[i].events & (POLLRDNORM | POLLIN)))
			{
				if((hdl = F->read_handler) != NULL)
				{
					F->read_handler = NULL;
					hdl(fd, F->read_data);
					/*
					 * this call used to be with a NULL pointer, BUT
					 * in the devpoll case we only want to update the
					 * poll set *if* the handler changes state (active ->
					 * NULL or vice versa.)
					 */
					devpoll_update_events(fd, COMM_SELECT_READ,
							      F->read_handler);
				}
				else
					ilog(L_NOTICE,
					     "comm_select: Unhandled read event: fdmask: %x\n",
					     fdmask[fd]);
			}
			if((dopoll.dp_fds[i].revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
			   && (dopoll.dp_fds[i].events & (POLLWRNORM | POLLOUT)))
			{
				if((hdl = F->write_handler) != NULL)
				{
					F->write_handler = NULL;
					hdl(fd, F->write_data);
					/* See above similar code in the read case */
					devpoll_update_events(fd, COMM_SELECT_WRITE,
							      F->write_handler);
				}
				else
					ilog(L_NOTICE,
					     "comm_select: Unhandled write event: fdmask: %x\n",
					     fdmask[fd]);

			}
			if(dopoll.dp_fds[i].revents & POLLNVAL)
			{
				ilog(L_NOTICE, "revents was Invalid for %d\n", fd);
			}
		}
		return COMM_OK;
	}
	while (0);
	/* XXX Get here, we broke! */
	return 0;
}
Exemplo n.º 24
0
void
icpHandleUdp(int sock, void *data)
{
    int *N = &incoming_sockets_accepted;
    struct sockaddr_in from;
    socklen_t from_len;
    LOCAL_ARRAY(char, buf, SQUID_UDP_SO_RCVBUF);
    int len;
    int icp_version;
    int max = INCOMING_ICP_MAX;
    commSetSelect(sock, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
    while (max--) {
	from_len = sizeof(from);
	memset(&from, '\0', from_len);
	statCounter.syscalls.sock.recvfroms++;
	len = recvfrom(sock,
	    buf,
	    SQUID_UDP_SO_RCVBUF - 1,
	    0,
	    (struct sockaddr *) &from,
	    &from_len);
	if (len == 0)
	    break;
	if (len < 0) {
	    if (ignoreErrno(errno))
		break;
#ifdef _SQUID_LINUX_
	    /* Some Linux systems seem to set the FD for reading and then
	     * return ECONNREFUSED when sendto() fails and generates an ICMP
	     * port unreachable message. */
	    /* or maybe an EHOSTUNREACH "No route to host" message */
	    if (errno != ECONNREFUSED && errno != EHOSTUNREACH)
#endif
		debug(50, 1) ("icpHandleUdp: FD %d recvfrom: %s\n",
		    sock, xstrerror());
	    break;
	}
	(*N)++;
	icpCount(buf, RECV, (size_t) len, 0);
	buf[len] = '\0';
	debug(12, 4) ("icpHandleUdp: FD %d: received %d bytes from %s.\n",
	    sock,
	    len,
	    inet_ntoa(from.sin_addr));
#ifdef ICP_PACKET_DUMP
	icpPktDump(buf);
#endif
	if (len < sizeof(icp_common_t)) {
	    debug(12, 4) ("icpHandleUdp: Ignoring too-small UDP packet\n");
	    break;
	}
	icp_version = (int) buf[1];	/* cheat! */
	if (icp_version == ICP_VERSION_2)
	    icpHandleIcpV2(sock, from, buf, len);
	else if (icp_version == ICP_VERSION_3)
	    icpHandleIcpV3(sock, from, buf, len);
	else
	    debug(12, 1) ("WARNING: Unused ICP version %d received from %s:%d\n",
		icp_version,
		inet_ntoa(from.sin_addr),
		ntohs(from.sin_port));
    }
}
Exemplo n.º 25
0
TruncateOp::TruncateOp(bool newopen_file)
{
    this->open_file = newopen_file;
    // it's possible that we lost a race and some other proc already removed
    ignoreErrno(-ENOENT);
}
Exemplo n.º 26
0
int
comm_select(unsigned long delay)
{
	int num;
	int fd;
	PF *hdl;
	fde_t *F;
	struct timeval to;

	/* Copy over the read/write sets so we don't have to rebuild em */
	memcpy(&tmpreadfds, &select_readfds, sizeof(fd_set));
	memcpy(&tmpwritefds, &select_writefds, sizeof(fd_set));

	for (;;)
	{
		to.tv_sec = 0;
		to.tv_usec = delay * 1000;
		num = select(highest_fd + 1, &tmpreadfds, &tmpwritefds, NULL, &to);
		if(num >= 0)
			break;
		if(ignoreErrno(errno))
			continue;
		set_time();
		/* error! */
		return -1;
		/* NOTREACHED */
	}
	set_time();

	if(num == 0)
		return 0;

	/* XXX we *could* optimise by falling out after doing num fds ... */
	for (fd = 0; fd < highest_fd + 1; fd++)
	{
		F = &fd_table[fd];

		if(FD_ISSET(fd, &tmpreadfds))
		{
			hdl = F->read_handler;
			F->read_handler = NULL;
			if(hdl)
				hdl(fd, F->read_data);
		}

		if(F->flags.open == 0)
			continue;	/* Read handler closed us..go on */

		if(FD_ISSET(fd, &tmpwritefds))
		{
			hdl = F->write_handler;
			F->write_handler = NULL;
			if(hdl)
				hdl(fd, F->write_data);
		}

		if(F->read_handler == NULL)
			select_update_selectfds(fd, COMM_SELECT_READ, NULL);
		if(F->write_handler == NULL)
			select_update_selectfds(fd, COMM_SELECT_WRITE, NULL);
	}
	return 0;
}
Exemplo n.º 27
0
/*
 * read_pptp_header
 *
 * Reads a packet from a file descriptor and determines whether it is a
 * valid PPTP Control Message. If a valid PPTP Control Message is detected
 * it extracts the Control Message type from the packet header.
 *
 * args:        clientFd (IN) - Clients file descriptor.
 *              packet (OUT) - Packet we read from the client.
 *              pptp_ctrl_type (OUT) - PPTP Control Message type of the packet.
 *
 * retn:        Number of bytes read on success.
 *              -1 on retryable error.
 *              0 on error to exit on.
 */
ssize_t read_pptp_header(int clientFd, unsigned char *packet, int *pptp_ctrl_type)
{

        ssize_t bytes_ttl, bytes_this;  /* quantities read (total and this read) */
        u_int16_t length;               /* length of this packet */
        struct pptp_header *header;     /* the received header */

        static char *buffer = NULL;     /* buffer between calls */
        static int buffered = 0;        /* size of buffer */

        *pptp_ctrl_type = 0;            /* initialise return arg        */

        /* read any previously buffered data */
        if (buffered) {
                memcpy(packet, buffer, buffered);
                free(buffer);
                buffer = NULL;
                bytes_ttl = buffered;
                buffered = 0;
                if (pptpctrl_debug)
                        syslog(LOG_DEBUG, "CTRL: Read in previous incomplete ctrl packet");
        } else
                bytes_ttl = 0;

        /* try and get the length in */
        if (bytes_ttl < 2) {
                bytes_this = read(clientFd, packet + bytes_ttl, 2 - bytes_ttl);
                switch (bytes_this) {
                case -1:
                        if (ignoreErrno(errno)) {
                                /* re-tryable error, re-buffer and return */
                                if (bytes_ttl) {
                                        buffered = bytes_ttl;
                                        buffer = malloc(bytes_ttl);
                                        if (!buffer)
                                                return(0);
                                        memcpy(buffer, packet, bytes_ttl);
                                }
                                syslog(LOG_ERR, "CTRL: Error reading ctrl packet length (bytes_ttl=%lu): %s", (unsigned long) bytes_ttl, strerror(errno));
                                return -1;
                        }
                        /* FALLTHRU */
                case 0:
                        syslog(LOG_ERR, "CTRL: EOF or bad error reading ctrl packet length.");
                        return 0;
                default:
                        bytes_ttl += bytes_this;
                        /* Not enough data to proceed */
                        if (bytes_ttl == 1) {
                                buffered = bytes_ttl;
                                buffer = malloc(bytes_ttl);
                                if (!buffer)
                                        return(0);
                                memcpy(buffer, packet, bytes_ttl);
                                if (pptpctrl_debug)
                                        syslog(LOG_DEBUG, "CTRL: Incomplete ctrl packet length, retry later");
                                return -1;
                        }
                }
        }
        /* OK, we have (at least) the first 2 bytes, and there is data waiting
         *
         * length includes the header,  so a length less than 2 is someone
         * trying to hack into us or a badly corrupted packet.
         * Why not require length to be at least 10? Since we later cast
         * packet to struct pptp_header and use at least the 10 first bytes..
         * Thanks to Timo Sirainen for mentioning this.
         */
        length = htons(*(u_int16_t *) packet);
        if (length <= 10 || length > PPTP_MAX_CTRL_PCKT_SIZE) {
                syslog(LOG_ERR, "CTRL: 11 < Control packet (length=%d) < "
                                "PPTP_MAX_CTRL_PCKT_SIZE (%d)",
                                length, PPTP_MAX_CTRL_PCKT_SIZE);
                /* we loose sync (unless we malloc something big, which isn't a good
                 * idea - potential DoS) so we must close connection (draft states that
                 * if you loose sync you must close the control connection immediately)
                 */
                return 0;
        }
        /* Now read the actual control packet */
        bytes_this = read(clientFd, packet + bytes_ttl, length - bytes_ttl);
        switch (bytes_this) {
        case -1:
                if(ignoreErrno(errno)) {
                        /* re-tryable error, re-buffer and return */
                        if (bytes_ttl) {
                                buffered = bytes_ttl;
                                buffer = malloc(bytes_ttl);
                                if (!buffer)
                                        return(0);
                                memcpy(buffer, packet, bytes_ttl);
                        }
                        syslog(LOG_ERR, "CTRL: Error reading ctrl packet (bytes_ttl=%lu,length=%d): %s", (unsigned long) bytes_ttl, length, strerror(errno));
                        return -1;
                }
                /* FALLTHRU */
        case 0:
                syslog(LOG_ERR, "CTRL: EOF or bad error reading ctrl packet.");
                return 0;
        default:
                bytes_ttl += bytes_this;
                /* not enough data to proceed */
                if (bytes_ttl != length) {
                        buffered = bytes_ttl;
                        buffer = malloc(bytes_ttl);
                        if (!buffer)
                                return(0);
                        memcpy(buffer, packet, bytes_ttl);
                        if (pptpctrl_debug)
                                syslog(LOG_DEBUG, "CTRL: Incomplete ctrl packet, retry later");
                        return -1;
                }
        }

        /* We got one :-) */

        /* Cast the packet into the PPTP Control Message format */
        header = (struct pptp_header *) packet;

        /* Packet sanity check on magic cookie */
        if (ntohl(header->magic) != PPTP_MAGIC_COOKIE) {
                /* Oops! Not a valid Control Message */
                syslog(LOG_ERR, "CTRL: Bad magic cookie - lost syncronization, closing control connection.");
                /* draft states loss of syncronization must result in
                 * immediate closing of the control connection
                 */
                return 0;
        }
        /* Woohoo! Looks like we got a valid PPTP packet */
        *pptp_ctrl_type = (int) (ntohs(header->ctrl_type));
        if (pptpctrl_debug)
                syslog(LOG_DEBUG, "CTRL: Received PPTP Control Message (type: %d)", *pptp_ctrl_type);
        return bytes_ttl;
}
Exemplo n.º 28
0
/* void comm_select(unsigned long delay)
 * Input: The maximum time to delay.
 * Output: None
 * Side-effects: Deregisters future interest in IO and calls the handlers
 *               if an event occurs for an FD.
 * Comments: Check all connections for new connections and input data
 * that is to be processed. Also check for connections with data queued
 * and whether we can write it out.
 * Called to do the new-style IO, courtesy of squid (like most of this
 * new IO code). This routine handles the stuff we've hidden in
 * comm_setselect and fd_table[] and calls callbacks for IO ready
 * events.
 */
void
comm_select(unsigned long delay)
{
  int revents = 0, sig, fd;
  PF *hdl;
  fde_t *F;
  struct siginfo si;
  struct timespec timeout;

  timeout.tv_sec = 0;
  timeout.tv_nsec = 1000000 * delay;
  sig = sigtimedwait(&our_sigset, &si, &timeout);
  set_time();
  if (sig != SIGIO)
  {
    if (sig > 0)
    {
      fd = si.si_fd;
      pollfd_list.pollfds[fd].revents |= si.si_band;
      revents = pollfd_list.pollfds[fd].revents;
      F = &fd_table[fd];
      if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
      {
        hdl = F->read_handler;
        F->read_handler = NULL;
        poll_update_pollfds(fd, POLLIN, NULL);
        if (hdl)
          hdl(fd, F->read_data);
      }
      if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
      {
        hdl = F->write_handler;
        F->write_handler = NULL;
        poll_update_pollfds(fd, POLLOUT, NULL);
        if (hdl)
          hdl(fd, F->write_data);
      }
    }
    return;
  }

  /* RT signal queue overflowed.. */

  if (CurrentTime - last_rtsigqo_warning >= 30)
  {
    ilog(L_WARN, "Kernel RT Signal queue overflowed.  "
                 "Is /proc/sys/kernel/rtsig-max too small?");
    last_rtsigqo_warning = CurrentTime;
  }

  signal(SIGIO_SIGNAL, SIG_IGN);
  signal(SIGIO_SIGNAL, SIG_DFL);

  /* ..try polling instead */
  {
    int num, ci;

    while ((num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, 0)) < 0
           && ignoreErrno(errno))
      ;

    /* update current time again, eww.. */
    set_time();

    if (num > 0)
    {
      /* XXX we *could* optimise by falling out after doing num fds ... */
      for (ci = 0; ci < pollfd_list.maxindex + 1; ci++)
      {
        if (((revents = pollfd_list.pollfds[ci].revents) == 0) ||
            (pollfd_list.pollfds[ci].fd) == -1)
          continue;

        fd = pollfd_list.pollfds[ci].fd;
        F = &fd_table[fd];
        if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
        {
          hdl = F->read_handler;
          F->read_handler = NULL;
          poll_update_pollfds(fd, POLLIN, NULL);
          if (hdl)
            hdl(fd, F->read_data);
        }
        if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
        {
          hdl = F->write_handler;
          F->write_handler = NULL;
          poll_update_pollfds(fd, POLLOUT, NULL);
          if (hdl)
            hdl(fd, F->write_data);
        }
      }
    }
  }

  mask_our_signal(SIGIO_SIGNAL);
}
Exemplo n.º 29
0
/* write handler */
static void
diskHandleWrite(int fd, void *notused)
{
    int len = 0;
    fde *F = &fd_table[fd];
    struct _fde_disk *fdd = &F->disk;
    dwrite_q *q = fdd->write_q;
    int status = DISK_OK;
    int do_callback;
    int do_close;
    if (NULL == q)
	return;
    debug(6, 3) ("diskHandleWrite: FD %d\n", fd);
    F->flags.write_daemon = 0;
    assert(fdd->write_q != NULL);
    assert(fdd->write_q->len > fdd->write_q->buf_offset);
    debug(6, 3) ("diskHandleWrite: FD %d writing %d bytes\n",
	fd, (int) (fdd->write_q->len - fdd->write_q->buf_offset));
    errno = 0;
    if (fdd->write_q->file_offset != -1)
	lseek(fd, fdd->write_q->file_offset, SEEK_SET);
    len = FD_WRITE_METHOD(fd,
	fdd->write_q->buf + fdd->write_q->buf_offset,
	fdd->write_q->len - fdd->write_q->buf_offset);
    debug(6, 3) ("diskHandleWrite: FD %d len = %d\n", fd, len);
    statCounter.syscalls.disk.writes++;
    fd_bytes(fd, len, FD_WRITE);
    if (len < 0) {
	if (!ignoreErrno(errno)) {
	    status = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR;
	    debug(50, 1) ("diskHandleWrite: FD %d: disk write error: %s\n",
		fd, xstrerror());
	    /*
	     * If there is no write callback, then this file is
	     * most likely something important like a log file, or
	     * an interprocess pipe.  Its not a swapfile.  We feel
	     * that a write failure on a log file is rather important,
	     * and Squid doesn't otherwise deal with this condition.
	     * So to get the administrators attention, we exit with
	     * a fatal message.
	     */
	    if (fdd->wrt_handle == NULL)
		fatal("Write failure -- check your disk space and cache.log");
	    /*
	     * If there is a write failure, then we notify the
	     * upper layer via the callback, at the end of this
	     * function.  Meanwhile, flush all pending buffers
	     * here.  Let the upper layer decide how to handle the
	     * failure.  This will prevent experiencing multiple,
	     * repeated write failures for the same FD because of
	     * the queued data.
	     */
	    do {
		fdd->write_q = q->next;
		if (q->free_func)
		    (q->free_func) (q->buf);
		if (q) {
		    memFree(q, MEM_DWRITE_Q);
		    q = NULL;
		}
	    } while ((q = fdd->write_q));
	}
	len = 0;
    }
    if (q != NULL) {
	/* q might become NULL from write failure above */
	q->buf_offset += len;
	if (q->buf_offset > q->len)
	    debug(50, 1) ("diskHandleWrite: q->buf_offset > q->len (%p,%d, %d, %d FD %d)\n",
		q, (int) q->buf_offset, (int) q->len, len, fd);
	assert(q->buf_offset <= q->len);
	if (q->buf_offset == q->len) {
	    /* complete write */
	    fdd->write_q = q->next;
	    if (q->free_func)
		(q->free_func) (q->buf);
	    if (q) {
		memFree(q, MEM_DWRITE_Q);
		q = NULL;
	    }
	}
    }
    if (fdd->write_q == NULL) {
	/* no more data */
	fdd->write_q_tail = NULL;
    } else {
	/* another block is queued */
	diskCombineWrites(fdd);
	cbdataLock(fdd->wrt_handle_data);
	commSetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0);
	F->flags.write_daemon = 1;
    }
    do_close = F->flags.close_request;
    if (fdd->wrt_handle) {
	if (fdd->wrt_handle_data == NULL)
	    do_callback = 1;
	else if (cbdataValid(fdd->wrt_handle_data))
	    do_callback = 1;
	else
	    do_callback = 0;
	if (fdd->wrt_handle_data != NULL)
	    cbdataUnlock(fdd->wrt_handle_data);
	if (do_callback) {
	    fdd->wrt_handle(fd, status, len, fdd->wrt_handle_data);
	    /*
	     * NOTE, this callback can close the FD, so we must
	     * not touch 'F', 'fdd', etc. after this.
	     */
	    return;
	}
    }
    if (do_close)
	file_close(fd);
}
Exemplo n.º 30
0
/* int comm_select_fdlist(unsigned long delay)
 * Input: The maximum time to delay.
 * Output: Returns -1 on error, 0 on success.
 * Side-effects: Deregisters future interest in IO and calls the handlers
 *               if an event occurs for an FD.
 * Comments: Check all connections for new connections and input data
 * that is to be processed. Also check for connections with data queued
 * and whether we can write it out.
 * Called to do the new-style IO, courtesy of squid (like most of this
 * new IO code). This routine handles the stuff we've hidden in
 * comm_setselect and fd_table[] and calls callbacks for IO ready
 * events.
 */
int
comm_select(unsigned long delay)
{
	int num;
	int fd;
	int ci;
	unsigned long ndelay;
	PF *hdl;

	if(last_count > 0)
	{
		empty_count = 0;
		ndelay = 0;
	}
	else {
		ndelay = ++empty_count * 15000 ;
		if(ndelay > delay * 1000)
			ndelay = delay * 1000;	
	}
	
	for (;;)
	{
		/* XXX kill that +1 later ! -- adrian */
		if(ndelay > 0)
			irc_sleep(ndelay); 
		last_count = num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, 0);
		if(num >= 0)
			break;
		if(ignoreErrno(errno))
			continue;
		/* error! */
		set_time();
		return -1;
		/* NOTREACHED */
	}

	/* update current time again, eww.. */
	set_time();

	if(num == 0)
		return 0;
	/* XXX we *could* optimise by falling out after doing num fds ... */
	for (ci = 0; ci < pollfd_list.maxindex + 1; ci++)
	{
		fde_t *F;
		int revents;
		if(((revents = pollfd_list.pollfds[ci].revents) == 0) ||
		   (pollfd_list.pollfds[ci].fd) == -1)
			continue;
		fd = pollfd_list.pollfds[ci].fd;
		F = &fd_table[fd];
		if(revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
		{
			hdl = F->read_handler;
			F->read_handler = NULL;
			poll_update_pollfds(fd, POLLRDNORM, NULL);
			if(hdl)
				hdl(fd, F->read_data);
		}
		if(revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
		{
			hdl = F->write_handler;
			F->write_handler = NULL;
			poll_update_pollfds(fd, POLLWRNORM, NULL);
			if(hdl)
				hdl(fd, F->write_data);
		}
	}
	return 0;
}