Example #1
0
int acl_timed_connect(ACL_SOCKET sock, const struct sockaddr * sa,
	socklen_t len, int timeout)
{
	int   err;

	/*
	 * Sanity check. Just like with timed_wait(), the timeout must be a
	 * positive number.
	 */
	if (timeout < 0)
		acl_msg_panic("timed_connect: bad timeout: %d", timeout);

	/*
	 * Start the connection, and handle all possible results.
	 */
	if (acl_sane_connect(sock, sa, len) == 0)
		return (0);

	errno = acl_last_error();

#ifdef	ACL_UNIX
	if (errno != ACL_EINPROGRESS)
		return (-1);
#elif defined(ACL_WINDOWS)
	if (errno != ACL_EINPROGRESS && errno != ACL_EWOULDBLOCK)
		return (-1);
#endif

	/*
	 * A connection is in progress. Wait for a limited amount of time for
	 * something to happen. If nothing happens, report an error.
	 */
	if (acl_write_wait(sock, timeout) < 0)
		return (-1);

	/*
	 * Something happened. Some Solaris 2 versions have getsockopt() itself
	 * return the error, instead of returning it via the parameter list.
	 */
	len = sizeof(err);
	if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *) &err, &len) < 0) {
#ifdef  SUNOS5
	/*
	 * Solaris 2.4's socket emulation doesn't allow you
	 * to determine the error from a failed non-blocking
	 * connect and just returns EPIPE.  Create a fake
	 * error message for connect.   -- [email protected]
	 */
		if (errno == EPIPE)
			acl_set_error(ACL_ENOTCONN);
#endif
		return (-1);
	}

	if (err != 0) {
		acl_set_error(err);
		return (-1);
	} else
		return (0);
}
Example #2
0
int acl_read_wait(ACL_SOCKET fd, int timeout)
{
	const char *myname = "acl_read_wait";
	struct pollfd fds;
	int   delay = timeout * 1000;

	fds.events = POLLIN | POLLHUP | POLLERR;
	fds.fd = fd;

	acl_set_error(0);

	for (;;) {
		switch (poll(&fds, 1, delay)) {
		case -1:
			if (acl_last_error() == ACL_EINTR)
				continue;

			acl_msg_error("%s(%d), %s: poll error(%s), fd: %d",
				__FILE__, __LINE__, myname,
				acl_last_serror(), (int) fd);
			return -1;
		case 0:
			acl_set_error(ACL_ETIMEDOUT);
			return -1;
		default:
			if (fds.revents & (POLLHUP | POLLERR))
				return -1;
			else if ((fds.revents & POLLIN))
				return 0;
			else
				return -1;
		}
	}
}
Example #3
0
int acl_pthread_setspecific(acl_pthread_key_t key, void *value)
{
	const char *myname = "acl_pthread_setspecific";
	ACL_FIFO *tls_value_list_ptr = tls_value_list_get();
	ACL_ITER iter;

	if (key < 0 || key >= ACL_PTHREAD_KEYS_MAX) {
		acl_msg_error("%s(%d): key(%d) invalid",
			myname, __LINE__, key);
		acl_set_error(ACL_EINVAL);
		return ACL_EINVAL;
	}
	if (__tls_key_list[key].key != key) {
		acl_msg_error("%s(%d): __tls_key_list[%d].key(%d) != key(%d)",
			myname, __LINE__, key, __tls_key_list[key].key, key);
		acl_set_error(ACL_EINVAL);
		return ACL_EINVAL;
	}

	acl_foreach(iter, tls_value_list_ptr) {
		TLS_VALUE *tls_value = (TLS_VALUE*) iter.data;
		if (tls_value->tls_key != NULL
			&& tls_value->tls_key->key == key)
		{
			/* 如果相同的键存在则需要先释放旧数据 */
			if (tls_value->tls_key->destructor && tls_value->value)
				tls_value->tls_key->destructor(tls_value->value);
			tls_value->tls_key = NULL;
			tls_value->value = NULL;
			break;
		}
	}
Example #4
0
ACL_FILE_HANDLE acl_file_open(const char *filepath, int flags, int mode)
{
	ACL_FILE_HANDLE fh;
	DWORD fileaccess = 0, fileshare = 0, filecreate = 0, fileattr = 0;

        /* decode the access flags */
	switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) {
	case O_RDONLY:         /* read access */
		fileaccess = GENERIC_READ;
		break;
	case O_WRONLY:         /* write access */
		fileaccess = GENERIC_WRITE;
		if ((flags & O_APPEND) != 0)
			fileaccess |= FILE_APPEND_DATA;
		break;
	case O_RDWR:           /* read and write access */
		fileaccess = GENERIC_READ | GENERIC_WRITE;
		if ((flags & O_APPEND) != 0)
			fileaccess = GENERIC_READ | FILE_APPEND_DATA;
		break;
	default:                /* error, bad flags */
		acl_set_error(ERROR_INVALID_PARAMETER);
		return ACL_FILE_INVALID;
	}

        /* decode open/create method flags */
	switch (flags & (O_CREAT | O_EXCL | O_TRUNC)) {
	case 0:
	case O_EXCL:            /* ignore EXCL w/o CREAT */
		filecreate = OPEN_EXISTING;
		break;
	case O_CREAT:
		filecreate = OPEN_ALWAYS;
		break;
	case O_CREAT | O_EXCL:
	case O_CREAT | O_TRUNC | O_EXCL:
		filecreate = CREATE_NEW;
		break;
	case O_TRUNC:
	case O_TRUNC | O_EXCL:  /* ignore EXCL w/o CREAT */
		filecreate = TRUNCATE_EXISTING;
		break;
	case O_CREAT | O_TRUNC:
		filecreate = CREATE_ALWAYS;
		break;
	default:
		/* this can't happen ... all cases are covered */
		acl_set_error(ERROR_INVALID_PARAMETER);
		return ACL_FILE_INVALID;
	}

	fileshare |= FILE_SHARE_READ | FILE_SHARE_WRITE;
	fileattr = FILE_ATTRIBUTE_NORMAL;

	fh = CreateFile(filepath, fileaccess, fileshare, NULL,
			filecreate, fileattr, NULL);
	return fh;
}
Example #5
0
int acl_read_wait(ACL_SOCKET fd, int timeout)
{
    const char *myname = "acl_read_wait";
    struct pollfd fds;
    int   delay = timeout * 1000;
    time_t begin;

    fds.events = POLLIN | POLLHUP | POLLERR;
    fds.fd = fd;

    acl_set_error(0);

    for (;;) {
        time(&begin);

        switch (poll(&fds, 1, delay)) {
        case -1:
            if (acl_last_error() == ACL_EINTR)
                continue;

            acl_msg_error("%s(%d), %s: poll error(%s), fd: %d",
                          __FILE__, __LINE__, myname,
                          acl_last_serror(), (int) fd);
            return -1;
        case 0:
            acl_msg_warn("%s(%d), %s: poll timeout: %s, fd: %d, "
                         "delay: %d, spent: %ld", __FILE__, __LINE__,
                         myname, acl_last_serror(), fd, delay,
                         (long) (time(NULL) - begin));
            acl_set_error(ACL_ETIMEDOUT);
            return -1;
        default:
            if (fds.revents & (POLLHUP | POLLERR)) {
                acl_msg_warn("%s(%d), %s: poll error: %s, "
                             "fd: %d, delay: %d, spent: %ld",
                             __FILE__, __LINE__, myname,
                             acl_last_serror(), fd, delay,
                             (long) (time(NULL) - begin));
                return -1;
            } else if ((fds.revents & POLLIN))
                return 0;
            else {
                acl_msg_warn("%s(%d), %s: poll error: %s, "
                             "fd: %d, delay: %d, spent: %ld",
                             __FILE__, __LINE__, myname,
                             acl_last_serror(), fd, delay,
                             (long) (time(NULL) - begin));
                return -1;
            }
        }
    }
}
Example #6
0
int acl_pthread_attr_setstacksize(acl_pthread_attr_t *attr, size_t stacksize)
{
	if (attr == NULL) {
		acl_set_error(ACL_EINVAL);
		return ACL_EINVAL;
	}
	if (stacksize < PTHREAD_STACK_MIN) {
		acl_set_error(ACL_EINVAL);
		return ACL_EINVAL;
	}
	attr->stacksize = stacksize;
	return 0;
}
Example #7
0
_tDIR * _topendir(const _TCHAR *dirname)
{
	_TCHAR *name;
	int len;
	_tDIR *dir;
	HANDLE h;

	/* Allocate space for a copy of the directory name, plus
	* room for the "*.*" we will concatenate to the end.
	*/
	len = _tcslen(dirname);
	if ((name = malloc((len+5) * sizeof(_TCHAR))) == NULL) {
		acl_set_error(ENOMEM);
		return (NULL);
	}
	_tcscpy(name, dirname);
	if (len-- && name[len] != _TEXT(':') && name[len] != _TEXT('\\') && name[len] != _TEXT('/'))
		_tcscat(name,_TEXT("\\*.*"));
	else
		_tcscat(name,_TEXT("*.*"));

	/* Allocate space for a DIR structure.
	*/
	if ((dir = malloc(sizeof(_tDIR))) == NULL) {
		acl_set_error(ENOMEM);
		free(name);
		return (NULL);
	}

	/* Search for the first file to see if the directory exists,
	* and to obtain directory handle for future FindNextFile() calls.
	*/
	if ((h = FindFirstFile((LPSTR)name,
		(LPWIN32_FIND_DATA)&dir->_d_buf[0])) == (HANDLE)-1)	{
		free(name);
		free(dir);
		acl_set_error(ENOTDIR);     /* set error */
		return (NULL);
	}

	/* Everything is OK.  Save information in the DIR structure, return it.
	*/
	dir->_d_nfiles  = 1;
	dir->_d_hdir    = (unsigned long)h;
	dir->_d_dirname = name;
	dir->_d_magic   = DIRMAGIC;
	return dir;
}
Example #8
0
int acl_readable(ACL_SOCKET fd)
{
	const char *myname = "poll_read_wait";
	struct pollfd fds;
	int   delay = 0;

	fds.events = POLLIN;
	fds.fd = fd;

	acl_set_error(0);

	for (;;) {
		switch (poll(&fds, 1, delay)) {
		case -1:
			if (acl_last_error() == ACL_EINTR)
				continue;

			acl_msg_error("%s(%d), %s: poll error(%s), fd: %d",
				__FILE__, __LINE__, myname,
				acl_last_serror(), (int) fd);
			return -1;
		case 0:
			return 0;
		default:
			if ((fds.revents & POLLIN)) {
				return 1;
			} else if (fds.revents & (POLLHUP | POLLERR)) {
				return 1;
			} else {
				return 0;
			}
		}
	}
}
Example #9
0
struct _tdirent * _treaddir(_tDIR *dir)
{
	WIN32_FIND_DATA *ff;

	/* Verify the handle.
	*/
	if (dir->_d_magic != DIRMAGIC) {
		acl_set_error(EBADF);
		return (NULL);
	}

	/* If all files in the buffer have been returned, find some more files.
	*/
	if (dir->_d_nfiles == 0) {
		if (FindNextFile((HANDLE)dir->_d_hdir,
			(LPWIN32_FIND_DATA)&dir->_d_buf[0]) != TRUE)
			return (NULL);
	}
	else
		dir->_d_nfiles = 0;

	/* Return the filename of the current file in the buffer.
	*/
	ff = (WIN32_FIND_DATA *)(dir->_d_buf);
	return ((struct _tdirent *)&ff->cFileName[0]);
}
Example #10
0
int acl_set_eugid(uid_t euid, gid_t egid)
{
	int   saved_error = acl_last_error();
	char  tbuf[256];

	if (geteuid() != 0 && seteuid(0)) {
		acl_msg_error("set_eugid: seteuid(0): %s",
			acl_last_strerror(tbuf, sizeof(tbuf)));
		return -1;
	}
	if (setegid(egid) < 0) {
		acl_msg_error("set_eugid: setegid(%ld): %s", (long) egid,
			acl_last_strerror(tbuf, sizeof(tbuf)));
		return -1;
	}
	if (setgroups(1, &egid) < 0) {
		acl_msg_error("set_eugid: setgroups(%ld): %s", (long) egid,
			acl_last_strerror(tbuf, sizeof(tbuf)));
		return -1;
	}
	if (euid != 0 && seteuid(euid) < 0) {
		acl_msg_error("set_eugid: seteuid(%ld): %s", (long) euid,
			acl_last_strerror(tbuf, sizeof(tbuf)));
		return -1;
	}
	if (acl_msg_verbose)
		acl_msg_info("set_eugid: euid %ld egid %ld",
			(long) euid, (long) egid);

	acl_set_error(saved_error);
	return 0;
}
Example #11
0
static int poll_write_wait(ACL_SOCKET fd, int timeout)
{
	const char *myname = "poll_write_wait";
	struct pollfd fds;
	int   delay = timeout * 1000;

	fds.events = POLLOUT | POLLHUP | POLLERR;
	fds.fd = fd;

	for (;;) {
		switch (poll(&fds, 1, delay)) {
		case -1:
			if (acl_last_error() != ACL_EINTR) {
				char tbuf[256];
				acl_msg_error("%s: poll error(%s)", myname,
					acl_last_strerror(tbuf, sizeof(tbuf)));
				return (-1);
			}
			continue;
		case 0:
			acl_set_error(ACL_ETIMEDOUT);
			return (-1);
		default:
			if ((fds.revents & (POLLHUP | POLLERR))
				|| !(fds.revents & POLLOUT))
			{
				return (-1);
			}
			return (0);
		}
	}
}
Example #12
0
int ssl_aio_stream::__ssl_send(ACL_SOCKET, const void *buf, size_t len,
	int, ACL_VSTREAM*, void *ctx)
{
#ifdef HAS_POLARSSL
	ssl_aio_stream* cli = (ssl_aio_stream*) ctx;
	int   ret;

	while ((ret = ::ssl_write((ssl_context*) cli->ssl_,
		(unsigned char*) buf, len)) <= 0)
	{
		if (ret == POLARSSL_ERR_NET_WANT_READ
			|| ret == POLARSSL_ERR_NET_WANT_WRITE)
		{
			if (acl_last_error() != ACL_EWOULDBLOCK)
				acl_set_error(ACL_EWOULDBLOCK);
		}
		return ACL_VSTREAM_EOF;
	}
	return ret;
#else
	(void) buf;
	(void) len;
	(void) ctx;
	return -1;
#endif
}
Example #13
0
int acl_readable(ACL_SOCKET fd)
{
	const char *myname = "acl_readable";
	struct timeval tv;
	fd_set  rfds, xfds;
	int   errnum;

	/*
	 * Sanity checks.
	 */
	if ((unsigned) fd >= FD_SETSIZE)
		acl_msg_fatal("%s(%d), %s: fd %d does not fit in "
			"FD_SETSIZE: %d", __FILE__, __LINE__, myname,
			(int) fd, FD_SETSIZE);

	/*
	 * Initialize.
	 */
	FD_ZERO(&rfds);
	FD_SET(fd, &rfds);
	FD_ZERO(&xfds);
	FD_SET(fd, &xfds);
	tv.tv_sec = 0;
	tv.tv_usec = 0;

	acl_set_error(0);

	/*
	 * Loop until we have an authoritative answer.
	 */
	for (;;) {
		switch (select((int) fd + 1, &rfds, (fd_set *) 0,
			&xfds, &tv))
		{
		case -1:
			errnum = acl_last_error();
#ifdef	ACL_WINDOWS
			if (errnum == WSAEINPROGRESS
				|| errnum == WSAEWOULDBLOCK
				|| errnum == ACL_EINTR)
			{
				continue;
			}
#else
			if (errnum == ACL_EINTR)
				continue;
#endif
			acl_msg_error("%s(%d), %s: select error(%s), fd: %d",
				__FILE__, __LINE__, myname,
				acl_last_serror(), (int) fd);
			return -1;
		case 0:
			return 0;
		default:
			return FD_ISSET(fd, &rfds);
		}
	}
}
Example #14
0
int acl_pthread_attr_setdetachstate(acl_pthread_attr_t *thr_attr, int detached)
{
	if (thr_attr == NULL) {
		acl_set_error(ACL_EINVAL);
		return ACL_EINVAL;
	}
	thr_attr->detached = detached;
	return 0;
}
Example #15
0
int acl_pthread_attr_destroy(acl_pthread_attr_t *thr_attr)
{
	if (thr_attr == NULL) {
		acl_set_error(ACL_EINVAL);
		return ACL_EINVAL;
	}
	memset(&thr_attr->attr, 0, sizeof(thr_attr->attr));
	return 0;
}
Example #16
0
int acl_read_wait(ACL_SOCKET fd, int timeout)
{
	const char *myname = "acl_read_wait";
	int op = EPOLL_CTL_ADD, delay = timeout * 1000, *epoll_fd;
	struct epoll_event ee, events[1];

	acl_assert(acl_pthread_once(&epoll_once, thread_epoll_init) == 0);
	epoll_fd = (int*) acl_pthread_getspecific(epoll_key);
	if (epoll_fd == NULL) {
		epoll_fd = (int*) acl_mymalloc(sizeof(int));
		acl_assert(acl_pthread_setspecific(epoll_key, epoll_fd) == 0);
		if ((unsigned long) acl_pthread_self()
			== acl_main_thread_self())
		{
			main_epoll_read_fd = epoll_fd;
			atexit(main_epoll_end);
		}

		*epoll_fd = epoll_create(1);
	}

	ee.events = EPOLLIN | EPOLLHUP | EPOLLERR;
	ee.data.u64 = 0;
	ee.data.fd = fd;
	if (epoll_ctl(*epoll_fd, op, fd, &ee) == -1) {
		acl_msg_error("%s(%d): epoll_ctl error: %s, fd: %d",
			myname, __LINE__, acl_last_serror(), fd);
		return -1;
	}

	if (epoll_wait(*epoll_fd, events, 1, delay) == -1) {
		acl_msg_error("%s(%d): epoll_wait error: %s, fd: %d",
			myname, __LINE__, acl_last_serror(), fd);
		return -1;
	}

	if ((events[0].events & (EPOLLERR | EPOLLHUP)) != 0)
		return -1;

	if ((events[0].events & EPOLLIN) == 0) {
		acl_set_error(ACL_ETIMEDOUT);
		return -1;
	}

	ee.events = 0;
	ee.data.u64 = 0;
	ee.data.fd = fd;
	if (epoll_ctl(*epoll_fd, EPOLL_CTL_DEL, fd, &ee) == -1) {
		acl_msg_error("%s(%d): epoll_ctl error: %s, fd: %d",
			myname, __LINE__, acl_last_serror(), fd);
		return -1;
	}

	return 0;
}
Example #17
0
int acl_write_wait(ACL_SOCKET fd, int timeout)
{
	const char *myname = "acl_write_wait";
	struct pollfd fds;
	int   delay = timeout * 1000;

	fds.events = POLLOUT | POLLHUP | POLLERR;
	fds.fd = fd;

	acl_set_error(0);

	for (;;) {
		switch (poll(&fds, 1, delay)) {
		case -1:
			if (acl_last_error() == ACL_EINTR)
				continue;
			acl_msg_error("%s(%d), %s: poll error(%s), fd: %d",
				__FILE__, __LINE__, myname,
				acl_last_serror(), (int) fd);
			return -1;
		case 0:
			acl_set_error(ACL_ETIMEDOUT);
			return -1;
		default:
			if ((fds.revents & (POLLHUP | POLLERR))) {
				acl_msg_error("%s(%d), %s: fd: %d,"
					"POLLHUP: %s, POLLERR: %s",
					__FILE__, __LINE__, myname, fd,
					fds.revents & POLLHUP ? "yes" : "no",
					fds.revents & POLLERR ? "yes" : "no");
				return -1;
			}
			if (fds.revents & POLLOUT)
				return 0;
			acl_msg_error("%s(%d), %s: unknown error, fd: %d",
				__FILE__, __LINE__, myname, fd);
			return -1;
		}
	}
}
Example #18
0
bool thread_mutex::unlock(void)
{
	int ret = acl_pthread_mutex_unlock(mutex_);
	if (ret)
	{
#ifdef ACL_UNIX
		acl_set_error(ret);
		logger_error("pthread_mutex_unlock error %s", last_serror());
#endif
		return false;
	}
	return true;
}
Example #19
0
int acl_pthread_once(acl_pthread_once_t *once_control,
	void (*init_routine)(void))
{
	int   n = 0;

	if (once_control == NULL || init_routine == NULL) {
		acl_set_error(ACL_EINVAL);
		return ACL_EINVAL;
	}

	/* 只有第一个调用 InterlockedCompareExchange 的线程才会执行
	 * init_routine, 后续线程永远在 InterlockedCompareExchange
	 * 外运行,并且一直进入空循环直至第一个线程执行 init_routine
	 * 完毕并且将 *once_control 重新赋值, 只有在多核环境中多个线程
	 * 同时运行至此时才有可能出现短暂的后续线程空循环现象,如果
	 * 多个线程顺序至此,则因为 *once_control 已经被第一个线程重新
	 * 赋值而不会进入循环体内只所以如此处理,是为了保证所有线程在
	 * 调用 acl_pthread_once 返回前 init_routine 必须被调用且仅能
	 * 被调用一次, 但在VC6下,InterlockedCompareExchange 接口定义
	 * 有些怪异,需要做硬性指定参数类型,参见 <Windows 高级编程指南>
	 * Jeffrey Richter, 366 页
	 */
	while (1) {
#ifdef MS_VC6
		LONG prev = InterlockedCompareExchange((PVOID) once_control,
			(PVOID) 1, (PVOID) ACL_PTHREAD_ONCE_INIT);
#else
		LONG prev = InterlockedCompareExchange(
			once_control, 1, ACL_PTHREAD_ONCE_INIT);
#endif
		if (prev == 2)
			return 0;
		else if (prev == 0) {
			/* 只有第一个线程才会至此 */
			init_routine();
			/* 将 *conce_control 重新赋值以使后续线程不进入 while
			 * 循环或从 while 循环中跳出
			 */
			InterlockedExchange(once_control, 2);
			return 0;
		} else {
			acl_assert(prev == 1);

			/* 防止空循环过多地浪费CPU */
			Sleep(1);  /** sleep 1ms */
		}
	}
	return 1;  /* 不可达代码,避免编译器报警告 */
}
Example #20
0
int _tclosedir(_tDIR *dir)
{
	/* Verify the handle.
	*/
	if (dir == NULL || dir->_d_magic != DIRMAGIC) {
		acl_set_error(EBADF);
		return (-1);
	}

	dir->_d_magic = 0;              /* prevent accidental use after closing */
	FindClose((HANDLE)dir->_d_hdir);/* close directory handle */
	free(dir->_d_dirname);          /* free directory name */
	free(dir);                      /* free directory structure */
	return 0;
}
Example #21
0
int acl_pthread_key_create(acl_pthread_key_t *key_ptr,
	void (*destructor)(void*))
{
	const char *myname = "acl_pthread_key_create";

	acl_pthread_once(&__create_thread_control_once, acl_pthread_init_once);

	*key_ptr = TlsAlloc();
	if (*key_ptr == ACL_TLS_OUT_OF_INDEXES) {
		acl_set_error(ACL_ENOMEM);
		return ACL_ENOMEM;
	} else if (*key_ptr >= ACL_PTHREAD_KEYS_MAX) {
		acl_msg_error("%s(%d): key(%d) > ACL_PTHREAD_KEYS_MAX(%d)",
			myname, __LINE__, *key_ptr, ACL_PTHREAD_KEYS_MAX);
		TlsFree(*key_ptr);
		*key_ptr = ACL_TLS_OUT_OF_INDEXES;
		acl_set_error(ACL_ENOMEM);
		return ACL_ENOMEM;
	}

	__tls_key_list[*key_ptr].destructor = destructor;
	__tls_key_list[*key_ptr].key = *key_ptr;
	return 0;
}
Example #22
0
int acl_pthread_attr_init(acl_pthread_attr_t *thr_attr)
{
	if (thr_attr == NULL) {
		acl_set_error(ACL_EINVAL);
		return ACL_EINVAL;
	}

	memset(&thr_attr->attr, 0, sizeof(thr_attr->attr));
	thr_attr->attr.bInheritHandle = 1;
	thr_attr->attr.lpSecurityDescriptor = NULL;
	thr_attr->attr.nLength = sizeof(SECURITY_ATTRIBUTES);
	thr_attr->stacksize = 0;
	thr_attr->detached = 0;

	return 0;
}
Example #23
0
static int  __read_wait(ACL_SOCKET fd, int timeout)
{
	fd_set  read_fds;
	fd_set  except_fds;
	struct timeval tv;
	struct timeval *tp;

#ifdef	ACL_UNIX
	/*
	 * Sanity checks.
	 */
	acl_assert(FD_SETSIZE > (unsigned) fd);
#endif

	/*
	 * Use select() so we do not depend on alarm() and on signal() handlers.
	 * Restart the select when interrupted by some signal. Some select()
	 * implementations reduce the time to wait when interrupted, which is
	 * exactly what we want.
	 */
	FD_ZERO(&read_fds);
	FD_SET(fd, &read_fds);
	FD_ZERO(&except_fds);
	FD_SET(fd, &except_fds);
	if (timeout >= 0) {
		tv.tv_usec = 0;
		tv.tv_sec = timeout;
		tp = &tv;
	} else
		tp = 0;

	for (;;) {
		switch (select((int) fd + 1, &read_fds, (fd_set *) 0,
			&except_fds, tp))
		{
		case -1:
			if (acl_last_error() != ACL_EINTR)
				return -1;
			continue;
		case 0:
			acl_set_error(ACL_ETIMEDOUT);
			return (-1);
		default:
			return (0);
		}
	}
}
Example #24
0
int acl_timed_waitpid(pid_t pid, ACL_WAIT_STATUS_T *statusp, int options,
	int time_limit)
{
	const char *myname = "timed_waitpid";
	struct sigaction action;
	struct sigaction old_action;
	int     time_left;
	int     wpid;
	char    tbuf[256];

	/*
	 * Sanity checks.
	 */
	if (time_limit <= 0)
		acl_msg_panic("%s: bad time limit: %d", myname, time_limit);

	/*
	 * Set up a timer.
	 */
	sigemptyset(&action.sa_mask);
	action.sa_flags = 0;
	action.sa_handler = timed_wait_alarm;
	if (sigaction(SIGALRM, &action, &old_action) < 0)
		acl_msg_fatal("%s: sigaction(SIGALRM): %s", myname,
			acl_last_strerror(tbuf, sizeof(tbuf)));
	timed_wait_expired = 0;
	time_left = alarm(time_limit);

	/*
	 * Wait for only a limited amount of time.
	 */
	if ((wpid = waitpid(pid, statusp, options)) < 0 && timed_wait_expired)
		acl_set_error(ETIMEDOUT);

	/*
	 * Cleanup.
	 */
	alarm(0);
	if (sigaction(SIGALRM, &old_action, (struct sigaction *) 0) < 0)
		acl_msg_fatal("%s: sigaction(SIGALRM): %s", myname,
			acl_last_strerror(tbuf, sizeof(tbuf)));
	if (time_left)
		alarm(time_left);

	return (wpid);
}
Example #25
0
void acl_set_ugid(uid_t uid, gid_t gid)
{
	int   saved_error = acl_last_error();
	char  tbuf[256];

	if (geteuid() != 0)
		if (seteuid(0) < 0)
			acl_msg_fatal("seteuid(0): %s", acl_last_strerror(tbuf, sizeof(tbuf)));
	if (setgid(gid) < 0)
		acl_msg_fatal("setgid(%ld): %s", (long) gid,
			acl_last_strerror(tbuf, sizeof(tbuf)));
	if (setgroups(1, &gid) < 0)
		acl_msg_fatal("setgroups(1, &%ld): %s", (long) gid,
			acl_last_strerror(tbuf, sizeof(tbuf)));
	if (setuid(uid) < 0)
		acl_msg_fatal("setuid(%ld): %s", (long) uid,
			acl_last_strerror(tbuf, sizeof(tbuf)));
	if (acl_msg_verbose > 1)
		acl_msg_info("setugid: uid %ld gid %ld", (long) uid, (long) gid);
	acl_set_error(saved_error);
}
Example #26
0
int acl_readable(ACL_SOCKET fd)
{
	struct pollfd fds;
	int    delay = 0;

	fds.events = POLLIN | POLLPRI;
	fds.fd = fd;

	acl_set_error(0);

	for (;;) {
		switch (__sys_poll(&fds, 1, delay)) {
#ifdef ACL_WINDOWS
		case SOCKET_ERROR:
#else
		case -1:
#endif
			if (acl_last_error() == ACL_EINTR)
				continue;

			acl_msg_error("%s(%d), %s: poll error(%s), fd: %d",
				__FILE__, __LINE__, __FUNCTION__,
				acl_last_serror(), (int) fd);
			return -1;
		case 0:
			return 0;
		default:
			if ((fds.revents & POLLIN)) {
				return 1;
			} else if (fds.revents & (POLLHUP | POLLERR)) {
				return 1;
			} else {
				return 0;
			}
		}
	}
}
Example #27
0
int acl_myflock(ACL_FILE_HANDLE fd, int lock_style, int operation)
{
	int     status = 0;

	/*
	 * Sanity check.
	 */
	if ((operation & (ACL_FLOCK_OP_BITS)) != operation)
		acl_msg_panic("myflock: improper operation type: 0x%x", operation);

	switch (lock_style) {

	/*
	 * flock() does exactly what we need. Too bad it is not standard.
	 */
#ifdef ACL_HAS_FLOCK_LOCK
	case ACL_FLOCK_STYLE_FLOCK:
	{
		static int lock_ops[] = {
			LOCK_UN, LOCK_SH, LOCK_EX, -1,
			-1, LOCK_SH | LOCK_NB, LOCK_EX | LOCK_NB, -1
		};

		status = flock(fd, lock_ops[operation]);
		break;
	}
#endif

	/*
	 * fcntl() is standard and does more than we need, but we can handle
	 * it.
	 */
#ifdef ACL_HAS_FCNTL_LOCK
	case ACL_FLOCK_STYLE_FCNTL:
	{
		struct flock lock;
		int     request;
		static int lock_ops[] = {
			F_UNLCK, F_RDLCK, F_WRLCK
		};

		memset((char *) &lock, 0, sizeof(lock));
		lock.l_type = lock_ops[operation & ~ACL_FLOCK_OP_NOWAIT];
		request = (operation & ACL_FLOCK_OP_NOWAIT) ? F_SETLK : F_SETLKW;
		while ((status = fcntl(fd, request, &lock)) < 0
			&& request == F_SETLKW
			&& (acl_last_error() == ACL_EINTR
			    || acl_last_error() == ENOLCK
				|| acl_last_error() == EDEADLK))
			sleep(1);
		break;
	}
#endif
	default:
		acl_msg_panic("myflock: unsupported lock style: 0x%x", lock_style);
	}

	/*
	 * Return a consistent result. Some systems return EACCES when a lock is
	 * taken by someone else, and that would complicate error processing.
	 */
	if (status < 0 && (operation & ACL_FLOCK_OP_NOWAIT) != 0) {
		char  error = acl_last_error();
		if (error == ACL_EAGAIN || error == ACL_EWOULDBLOCK || error == EACCES)
			acl_set_error(ACL_EAGAIN);
	}

	return (status);
}
Example #28
0
int acl_read_wait(ACL_SOCKET fd, int timeout)
{
    const char *myname = "acl_read_wait";
    fd_set  rfds, xfds;
    struct timeval tv;
    struct timeval *tp;
    int  errnum;
    time_t begin;

    /*
     * Sanity checks.
     */
#ifndef ACL_WINDOWS
    if (FD_SETSIZE <= (unsigned) fd)
        acl_msg_fatal("%s(%d), %s: descriptor %d does not fit "
                      "FD_SETSIZE %d", __FILE__, __LINE__, myname,
                      (int) fd, FD_SETSIZE);
#endif

    /*
     * Guard the write() with select() so we do not depend on alarm()
     * and on signal() handlers. Restart the select when interrupted
     * by some signal. Some select() implementations may reduce the
     * time to wait when interrupted, which is exactly what we want.
     */
    FD_ZERO(&rfds);
    FD_SET(fd, &rfds);
    FD_ZERO(&xfds);
    FD_SET(fd, &xfds);

    if (timeout >= 0) {
        tv.tv_usec = 0;
        tv.tv_sec = timeout;
        tp = &tv;
    } else
        tp = 0;

    acl_set_error(0);

    for (;;) {
        time(&begin);

#ifdef ACL_WINDOWS
        switch (select(1, &rfds, (fd_set *) 0, &xfds, tp)) {
#else
        switch (select(fd + 1, &rfds, (fd_set *) 0, &xfds, tp)) {
#endif
        case -1:
            errnum = acl_last_error();
#ifdef	ACL_WINDOWS
            if (errnum == WSAEINPROGRESS
                    || errnum == WSAEWOULDBLOCK
                    || errnum == ACL_EINTR)
            {
                continue;
            }
#else
            if (errnum == ACL_EINTR)
                continue;
#endif
            acl_msg_error("%s(%d), %s: select error(%s), fd: %d",
                          __FILE__, __LINE__, myname,
                          acl_last_serror(), (int) fd);
            return -1;
        case 0:
            acl_msg_warn("%s(%d), %s: poll timeout: %s, fd: %d, "
                         "timeout: %d, spent: %ld", __FILE__, __LINE__,
                         myname, acl_last_serror(), fd, timeout,
                         (long) (time(NULL) - begin));

            acl_set_error(ACL_ETIMEDOUT);
            return -1;
        default:
            return 0;
        }
    }
}
Example #29
0
int acl_read_wait(ACL_SOCKET fd, int timeout)
{
    const char *myname = "acl_read_wait";
    int   delay = timeout * 1000, ret;
    EPOLL_CTX *epoll_ctx;
    struct epoll_event ee, events[1];
    time_t begin;

    acl_assert(acl_pthread_once(&epoll_once, thread_epoll_once) == 0);
    epoll_ctx = (EPOLL_CTX*) acl_pthread_getspecific(epoll_key);
    if (epoll_ctx == NULL)
        epoll_ctx = thread_epoll_init();

    ee.events = EPOLLIN | EPOLLHUP | EPOLLERR;
    ee.data.u64 = 0;
    ee.data.fd = fd;
    if (epoll_ctl(epoll_ctx->epfd, EPOLL_CTL_ADD, fd, &ee) == -1
            && acl_last_error() != EEXIST)
    {
        acl_msg_error("%s(%d): epoll_ctl error: %s, fd: %d, epfd: %d,"
                      " tid: %lu, %lu", myname, __LINE__, acl_last_serror(),
                      fd, epoll_ctx->epfd, epoll_ctx->tid,
                      acl_pthread_self());
        return -1;
    }

    for (;;) {
        time(&begin);

        ret = epoll_wait(epoll_ctx->epfd, events, 1, delay);
        if (ret == -1) {
            if (acl_last_error() == ACL_EINTR) {
                acl_msg_warn(">>>>catch EINTR, try again<<<");
                continue;
            }

            acl_msg_error("%s(%d): epoll_wait error: %s, fd: %d,"
                          " epfd: %d, tid: %lu, %lu", myname, __LINE__,
                          acl_last_serror(), fd, epoll_ctx->epfd,
                          epoll_ctx->tid, acl_pthread_self());
            ret = -1;
            break;
        } else if (ret == 0) {
            acl_msg_warn("%s(%d), %s: poll timeout: %s, fd: %d, "
                         "delay: %d, spent: %ld", __FILE__, __LINE__,
                         myname, acl_last_serror(), fd, delay,
                         (long) (time(NULL) - begin));
            acl_set_error(ACL_ETIMEDOUT);
            ret = -1;
            break;
        } else if ((events[0].events & (EPOLLERR | EPOLLHUP)) != 0) {
            acl_msg_warn("%s(%d), %s: poll error: %s, fd: %d, "
                         "delay: %d, spent: %ld", __FILE__, __LINE__,
                         myname, acl_last_serror(), fd, delay,
                         (long) (time(NULL) - begin));
            ret = -1;
        } else if ((events[0].events & EPOLLIN) == 0) {
            acl_msg_warn("%s(%d), %s: poll error: %s, fd: %d, "
                         "delay: %d, spent: %ld", __FILE__, __LINE__,
                         myname, acl_last_serror(), fd, delay,
                         (long) (time(NULL) - begin));
            acl_set_error(ACL_ETIMEDOUT);
            ret = -1;
        } else
            ret = 0;
        break;
    }

    ee.events = 0;
    ee.data.u64 = 0;
    ee.data.fd = fd;
    if (epoll_ctl(epoll_ctx->epfd, EPOLL_CTL_DEL, fd, &ee) == -1) {
        acl_msg_error("%s(%d): epoll_ctl error: %s, fd: %d, epfd: %d,"
                      " tid: %lu, %lu", myname, __LINE__, acl_last_serror(),
                      fd, epoll_ctx->epfd, epoll_ctx->tid,
                      acl_pthread_self());
        return -1;
    }

    return ret;
}
Example #30
0
int  acl_pthread_create(acl_pthread_t *thread, acl_pthread_attr_t *attr,
	void *(*start_routine)(void *), void *arg)
{
	const char *myname = "acl_pthread_create";
	acl_pthread_t *h_thread;
	HANDLE handle;
	unsigned long id, flag;
	
	if (thread == NULL) {
		acl_msg_error("%s, %s(%d): input invalid",
			__FILE__, myname, __LINE__);
		acl_set_error(ACL_EINVAL);
		return ACL_EINVAL;
	}
	acl_pthread_once(&__create_thread_control_once, acl_pthread_init_once);
	memset(thread, 0, sizeof(acl_pthread_t));

	h_thread = acl_default_calloc(__FILE__, __LINE__,
			1, sizeof(acl_pthread_t));
	if (h_thread == NULL) {
		acl_msg_error("%s, %s(%d): calloc error(%s)",
			__FILE__, myname, __LINE__, acl_last_serror());
		acl_set_error(ACL_ENOMEM);
		return ACL_ENOMEM;
	}

	if (attr != NULL)
		h_thread->detached = attr->detached;
	else
		h_thread->detached = 1;
	h_thread->start_routine = start_routine;
	h_thread->routine_arg   = arg;

	if (__thread_inited) {
		acl_pthread_mutex_lock(&__thread_lock);
		flag = 0;
	} else
		flag = CREATE_SUSPENDED;

#ifdef ACL_WIN32_STDC
	h_thread->handle = handle = (HANDLE) _beginthreadex(NULL,
			attr ? (unsigned int) attr->stacksize : 0,
			RunThreadWrap,
			(void *) h_thread,
			flag,
			&id);
#else
	h_thread->handle = handle = CreateThread(NULL,
			attr ? attr->stacksize : 0,,
			RunThreadWrap,
			h_thread,
			flag,
			&id);
#endif

	if (__thread_inited)
		acl_pthread_mutex_unlock(&__thread_lock);
	else if (flag == CREATE_SUSPENDED && handle != 0)
		ResumeThread(handle);
	if (handle == 0) {
		acl_msg_error("%s, %s(%d): CreateThread error(%s)",
			__FILE__, myname, __LINE__, acl_last_serror());
		return -1;
	}
	thread->start_routine = start_routine;
	thread->routine_arg   = arg;
	thread->id            = id;
	thread->handle        = 0;

	/* 根据线程的属性来确定线程创建时是分离模式还是非分离模式 */

	if (attr == NULL || attr->detached) {
		thread->detached = 1;
		return 0;
	}

	thread->detached = 0;
	thread->handle = handle;
	return 0;
}