192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly/* 292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * Copyright 2009, The Android Open Source Project 392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * 492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * Licensed under the Apache License, Version 2.0 (the "License"); 592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * you may not use this file except in compliance with the License. 692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * You may obtain a copy of the License at 792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * 892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * http://www.apache.org/licenses/LICENSE-2.0 992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * 1092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * Unless required by applicable law or agreed to in writing, software 1192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * distributed under the License is distributed on an "AS IS" BASIS, 1292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * See the License for the specific language governing permissions and 1492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * limitations under the License. 1592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly */ 1692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 1792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include <stdlib.h> 1892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include <errno.h> 1992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include <unistd.h> 2092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include <fcntl.h> 2192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include <sys/socket.h> 2292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include <sys/poll.h> 2392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 2492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include "cutils/abort_socket.h" 2592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 2692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellystruct asocket *asocket_init(int fd) { 2792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly int abort_fd[2]; 2892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly int flags; 2992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly struct asocket *s; 3092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 3192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* set primary socket to non-blocking */ 3292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly flags = fcntl(fd, F_GETFL); 3392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (flags == -1) 3492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return NULL; 3592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) 3692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return NULL; 3792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 3892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* create pipe with non-blocking write, so that asocket_close() cannot 3992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly block */ 4092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (pipe(abort_fd)) 4192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return NULL; 4292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly flags = fcntl(abort_fd[1], F_GETFL); 4392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (flags == -1) 4492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return NULL; 4592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (fcntl(abort_fd[1], F_SETFL, flags | O_NONBLOCK)) 4692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return NULL; 4792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 4892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly s = malloc(sizeof(struct asocket)); 4992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (!s) 5092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return NULL; 5192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 5292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly s->fd = fd; 5392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly s->abort_fd[0] = abort_fd[0]; 5492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly s->abort_fd[1] = abort_fd[1]; 5592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 5692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return s; 5792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly} 5892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 5992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellyint asocket_connect(struct asocket *s, const struct sockaddr *addr, 6092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly socklen_t addrlen, int timeout) { 6192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 6292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly int ret; 6392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 6492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly do { 6592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly ret = connect(s->fd, addr, addrlen); 6692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } while (ret && errno == EINTR); 6792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 6892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (ret && errno == EINPROGRESS) { 6992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* ready to poll() */ 7092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly socklen_t retlen; 7192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly struct pollfd pfd[2]; 7292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 7392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[0].fd = s->fd; 7492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[0].events = POLLOUT; 7592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[0].revents = 0; 7692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[1].fd = s->abort_fd[0]; 7792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[1].events = POLLIN; 7892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[1].revents = 0; 7992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 8092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly do { 8192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly ret = poll(pfd, 2, timeout); 8292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } while (ret < 0 && errno == EINTR); 8392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 8492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (ret < 0) 8592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 8692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly else if (ret == 0) { 8792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* timeout */ 8892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ETIMEDOUT; 8992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 9092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 9192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 9292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (pfd[1].revents) { 9392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* abort due to asocket_abort() */ 9492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ECANCELED; 9592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 9692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 9792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 9892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (pfd[0].revents) { 9992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (pfd[0].revents & POLLOUT) { 10092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* connect call complete, read return code */ 10192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly retlen = sizeof(ret); 10292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen)) 10392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 10492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* got connect() return code */ 10592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (ret) { 10692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ret; 10792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 10892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } else { 10992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* some error event on this fd */ 11092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ECONNABORTED; 11192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 11292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 11392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 11492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 11592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 11692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return ret; 11792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly} 11892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 11992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellyint asocket_accept(struct asocket *s, struct sockaddr *addr, 12092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly socklen_t *addrlen, int timeout) { 12192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 12292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly int ret; 12392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly struct pollfd pfd[2]; 12492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 12592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[0].fd = s->fd; 12692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[0].events = POLLIN; 12792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[0].revents = 0; 12892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[1].fd = s->abort_fd[0]; 12992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[1].events = POLLIN; 13092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[1].revents = 0; 13192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 13292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly do { 13392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly ret = poll(pfd, 2, timeout); 13492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } while (ret < 0 && errno == EINTR); 13592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 13692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (ret < 0) 13792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 13892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly else if (ret == 0) { 13992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* timeout */ 14092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ETIMEDOUT; 14192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 14292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 14392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 14492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (pfd[1].revents) { 14592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* abort due to asocket_abort() */ 14692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ECANCELED; 14792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 14892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 14992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 15092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (pfd[0].revents) { 15192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (pfd[0].revents & POLLIN) { 15292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* ready to accept() without blocking */ 15392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly do { 15492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly ret = accept(s->fd, addr, addrlen); 15592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } while (ret < 0 && errno == EINTR); 15692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } else { 15792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* some error event on this fd */ 15892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ECONNABORTED; 15992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 16092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 16192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 16292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 16392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return ret; 16492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly} 16592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 16692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellyint asocket_read(struct asocket *s, void *buf, size_t count, int timeout) { 16792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly int ret; 16892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly struct pollfd pfd[2]; 16992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 17092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[0].fd = s->fd; 17192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[0].events = POLLIN; 17292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[0].revents = 0; 17392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[1].fd = s->abort_fd[0]; 17492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[1].events = POLLIN; 17592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[1].revents = 0; 17692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 17792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly do { 17892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly ret = poll(pfd, 2, timeout); 17992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } while (ret < 0 && errno == EINTR); 18092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 18192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (ret < 0) 18292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 18392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly else if (ret == 0) { 18492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* timeout */ 18592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ETIMEDOUT; 18692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 18792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 18892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 18992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (pfd[1].revents) { 19092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* abort due to asocket_abort() */ 19192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ECANCELED; 19292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 19392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 19492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 19592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (pfd[0].revents) { 19692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (pfd[0].revents & POLLIN) { 19792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* ready to read() without blocking */ 19892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly do { 19992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly ret = read(s->fd, buf, count); 20092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } while (ret < 0 && errno == EINTR); 20192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } else { 20292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* some error event on this fd */ 20392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ECONNABORTED; 20492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 20592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 20692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 20792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 20892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return ret; 20992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly} 21092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 21192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellyint asocket_write(struct asocket *s, const void *buf, size_t count, 21292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly int timeout) { 21392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly int ret; 21492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly struct pollfd pfd[2]; 21592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 21692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[0].fd = s->fd; 21792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[0].events = POLLOUT; 21892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[0].revents = 0; 21992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[1].fd = s->abort_fd[0]; 22092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[1].events = POLLIN; 22192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly pfd[1].revents = 0; 22292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 22392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly do { 22492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly ret = poll(pfd, 2, timeout); 22592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } while (ret < 0 && errno == EINTR); 22692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 22792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (ret < 0) 22892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 22992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly else if (ret == 0) { 23092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* timeout */ 23192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ETIMEDOUT; 23292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 23392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 23492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 23592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (pfd[1].revents) { 23692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* abort due to asocket_abort() */ 23792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ECANCELED; 23892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 23992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 24092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 24192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly if (pfd[0].revents) { 242111bfcefc3cf0f14ad607a56fcf5d076131833a9Nick Pelly if (pfd[0].revents & POLLOUT) { 24392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* ready to write() without blocking */ 24492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly do { 24592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly ret = write(s->fd, buf, count); 24692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } while (ret < 0 && errno == EINTR); 24792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } else { 24892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* some error event on this fd */ 24992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly errno = ECONNABORTED; 25092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return -1; 25192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 25292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } 25392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 25492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly return ret; 25592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly} 25692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 25792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellyvoid asocket_abort(struct asocket *s) { 25892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly int ret; 25992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly char buf = 0; 26092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 26192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* Prevent further use of fd, without yet releasing the fd */ 26292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly shutdown(s->fd, SHUT_RDWR); 26392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 26492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* wake up calls blocked at poll() */ 26592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly do { 26692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly ret = write(s->abort_fd[1], &buf, 1); 26792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly } while (ret < 0 && errno == EINTR); 26892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly} 26992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 27092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellyvoid asocket_destroy(struct asocket *s) { 27192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly struct asocket s_copy = *s; 27292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 27392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* Clients should *not* be using these fd's after calling 27492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly asocket_destroy(), but in case they do, set to -1 so they cannot use a 27592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly stale fd */ 27692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly s->fd = -1; 27792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly s->abort_fd[0] = -1; 27892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly s->abort_fd[1] = -1; 27992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 28092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* Call asocket_abort() in case there are still threads blocked on this 28192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly socket. Clients should not rely on this behavior - it is racy because we 28292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly are about to close() these sockets - clients should instead make sure 28392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly all threads are done with the socket before calling asocket_destory(). 28492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly */ 28592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly asocket_abort(&s_copy); 28692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 28792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly /* enough safety checks, close and release memory */ 28892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly close(s_copy.abort_fd[1]); 28992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly close(s_copy.abort_fd[0]); 29092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly close(s_copy.fd); 29192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly 29292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly free(s); 29392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly} 294