Init Repo

This commit is contained in:
root
2019-09-06 23:53:10 +08:00
commit f0ef89dfbb
7905 changed files with 914138 additions and 0 deletions

676
vendor/swoole/src/os/base.c vendored Executable file
View File

@ -0,0 +1,676 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| Copyright (c) 2012-2018 The Swoole Group |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
#include "async.h"
#include <sys/file.h>
#include <sys/stat.h>
swAsyncIO SwooleAIO;
swPipe swoole_aio_pipe;
static void swAioBase_destroy();
static int swAioBase_read(int fd, void *inbuf, size_t size, off_t offset);
static int swAioBase_write(int fd, void *inbuf, size_t size, off_t offset);
static int swAioBase_thread_onTask(swThreadPool *pool, void *task, int task_len);
static int swAioBase_onFinish(swReactor *reactor, swEvent *event);
static void swAio_handler_read(swAio_event *event);
static void swAio_handler_write(swAio_event *event);
static void swAio_handler_gethostbyname(swAio_event *event);
static void swAio_handler_getaddrinfo(swAio_event *event);
static void swAio_handler_stream_get_line(swAio_event *event);
static void swAio_handler_read_file(swAio_event *event);
static void swAio_handler_write_file(swAio_event *event);
static swThreadPool swAioBase_thread_pool;
static int swAioBase_pipe_read;
static int swAioBase_pipe_write;
int swAio_init(void)
{
if (SwooleAIO.init)
{
swWarn("AIO has already been initialized");
return SW_ERR;
}
if (!SwooleG.main_reactor)
{
swWarn("No eventloop, cannot initialized");
return SW_ERR;
}
return swAioBase_init(SW_AIO_EVENT_NUM);
}
void swAio_free(void)
{
if (!SwooleAIO.init)
{
return;
}
SwooleAIO.destroy();
SwooleAIO.init = 0;
}
/**
* for test
*/
void swAio_callback_test(swAio_event *aio_event)
{
printf("content=%s\n", (char *)aio_event->buf);
printf("fd: %d, request_type: %s, offset: %ld, length: %lu\n", aio_event->fd,
(aio_event == SW_AIO_READ) ? "READ" : "WRITE", (long)aio_event->offset, aio_event->nbytes);
SwooleG.running = 0;
}
#ifndef HAVE_DAEMON
int daemon(int nochdir, int noclose)
{
pid_t pid;
if (!nochdir && chdir("/") != 0)
{
swWarn("chdir() failed. Error: %s[%d]", strerror(errno), errno);
return -1;
}
if (!noclose)
{
int fd = open("/dev/null", O_RDWR);
if (fd < 0)
{
swWarn("open() failed. Error: %s[%d]", strerror(errno), errno);
return -1;
}
if (dup2(fd, 0) < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0)
{
close(fd);
swWarn("dup2() failed. Error: %s[%d]", strerror(errno), errno);
return -1;
}
close(fd);
}
pid = fork();
if (pid < 0)
{
swWarn("fork() failed. Error: %s[%d]", strerror(errno), errno);
return -1;
}
if (pid > 0)
{
_exit(0);
}
if (setsid() < 0)
{
swWarn("setsid() failed. Error: %s[%d]", strerror(errno), errno);
return -1;
}
return 0;
}
#endif
static int swAioBase_onFinish(swReactor *reactor, swEvent *event)
{
int i;
swAio_event *events[SW_AIO_EVENT_NUM];
int n = read(event->fd, events, sizeof(swAio_event*) * SW_AIO_EVENT_NUM);
if (n < 0)
{
swWarn("read() failed. Error: %s[%d]", strerror(errno), errno);
return SW_ERR;
}
for (i = 0; i < n / sizeof(swAio_event*); i++)
{
if (events[i]->callback)
{
events[i]->callback(events[i]);
}
else
{
SwooleAIO.callback(events[i]);
}
SwooleAIO.task_num--;
sw_free(events[i]);
}
return SW_OK;
}
int swAioBase_init(int max_aio_events)
{
if (swPipeBase_create(&swoole_aio_pipe, 0) < 0)
{
return SW_ERR;
}
if (swMutex_create(&SwooleAIO.lock, 0) < 0)
{
swWarn("create mutex lock error.");
return SW_ERR;
}
if (SwooleAIO.thread_num <= 0)
{
SwooleAIO.thread_num = SW_AIO_THREAD_NUM_DEFAULT;
}
if (swThreadPool_create(&swAioBase_thread_pool, SwooleAIO.thread_num) < 0)
{
return SW_ERR;
}
swAioBase_thread_pool.onTask = swAioBase_thread_onTask;
swAioBase_pipe_read = swoole_aio_pipe.getFd(&swoole_aio_pipe, 0);
swAioBase_pipe_write = swoole_aio_pipe.getFd(&swoole_aio_pipe, 1);
SwooleAIO.handlers[SW_AIO_READ] = swAio_handler_read;
SwooleAIO.handlers[SW_AIO_WRITE] = swAio_handler_write;
SwooleAIO.handlers[SW_AIO_GETHOSTBYNAME] = swAio_handler_gethostbyname;
SwooleAIO.handlers[SW_AIO_GETADDRINFO] = swAio_handler_getaddrinfo;
SwooleAIO.handlers[SW_AIO_STREAM_GET_LINE] = swAio_handler_stream_get_line;
SwooleAIO.handlers[SW_AIO_READ_FILE] = swAio_handler_read_file;
SwooleAIO.handlers[SW_AIO_WRITE_FILE] = swAio_handler_write_file;
SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_AIO, swAioBase_onFinish);
SwooleG.main_reactor->add(SwooleG.main_reactor, swAioBase_pipe_read, SW_FD_AIO);
if (swThreadPool_run(&swAioBase_thread_pool) < 0)
{
return SW_ERR;
}
SwooleAIO.destroy = swAioBase_destroy;
SwooleAIO.read = swAioBase_read;
SwooleAIO.write = swAioBase_write;
SwooleAIO.init = 1;
return SW_OK;
}
static void swAio_handler_read(swAio_event *event)
{
int ret = -1;
if (flock(event->fd, LOCK_SH) < 0)
{
swSysError("flock(%d, LOCK_SH) failed.", event->fd);
event->ret = -1;
event->error = errno;
return;
}
while (1)
{
ret = pread(event->fd, event->buf, event->nbytes, event->offset);
if (ret < 0 && (errno == EINTR || errno == EAGAIN))
{
continue;
}
break;
}
if (flock(event->fd, LOCK_UN) < 0)
{
swSysError("flock(%d, LOCK_UN) failed.", event->fd);
}
event->ret = ret;
}
static inline char* find_eol(char *buf, size_t size)
{
char *eol = memchr(buf, '\n', size);
if (!eol)
{
eol = memchr(buf, '\r', size);
}
return eol;
}
static void swAio_handler_stream_get_line(swAio_event *event)
{
int ret = -1;
if (flock(event->fd, LOCK_SH) < 0)
{
swSysError("flock(%d, LOCK_SH) failed.", event->fd);
event->ret = -1;
event->error = errno;
return;
}
off_t readpos = event->offset;
off_t writepos = (long) event->req;
size_t avail = 0;
char *eol;
char *tmp;
char *read_buf = event->buf;
int read_n = event->nbytes;
while (1)
{
avail = writepos - readpos;
swTraceLog(SW_TRACE_AIO, "readpos=%ld, writepos=%ld", (long)readpos, (long)writepos);
if (avail > 0)
{
tmp = event->buf + readpos;
eol = find_eol(tmp, avail);
if (eol)
{
event->buf = tmp;
event->ret = (eol - tmp) + 1;
readpos += event->ret;
goto _return;
}
else if (readpos == 0)
{
if (writepos == event->nbytes)
{
writepos = 0;
event->ret = event->nbytes;
goto _return;
}
else
{
event->flags = SW_AIO_EOF;
((char*) event->buf)[writepos] = '\0';
event->ret = writepos;
writepos = 0;
goto _return;
}
}
else
{
memmove(event->buf, event->buf + readpos, avail);
writepos = avail;
read_buf = event->buf + writepos;
read_n = event->nbytes - writepos;
readpos = 0;
goto _readfile;
}
}
else
{
_readfile: while (1)
{
ret = read(event->fd, read_buf, read_n);
if (ret < 0 && (errno == EINTR || errno == EAGAIN))
{
continue;
}
break;
}
if (ret > 0)
{
writepos += ret;
}
else if (ret == 0)
{
event->flags = SW_AIO_EOF;
if (writepos > 0)
{
event->ret = writepos;
}
else
{
((char*) event->buf)[0] = '\0';
event->ret = 0;
}
readpos = writepos = 0;
goto _return;
}
}
}
_return:
if (flock(event->fd, LOCK_UN) < 0)
{
swSysError("flock(%d, LOCK_UN) failed.", event->fd);
}
event->offset = readpos;
event->req = (void *) (long) writepos;
}
static void swAio_handler_read_file(swAio_event *event)
{
int ret = -1;
int fd = open(event->req, O_RDONLY);
if (fd < 0)
{
swSysError("open(%s, O_RDONLY) failed.", (char * )event->req);
event->ret = ret;
event->error = errno;
return;
}
struct stat file_stat;
if (fstat(fd, &file_stat) < 0)
{
swSysError("fstat(%s) failed.", (char * )event->req);
_error: close(fd);
event->ret = ret;
event->error = errno;
return;
}
if ((file_stat.st_mode & S_IFMT) != S_IFREG)
{
errno = EISDIR;
goto _error;
}
long filesize = file_stat.st_size;
if (filesize == 0)
{
errno = SW_ERROR_FILE_EMPTY;
goto _error;
}
if (flock(fd, LOCK_SH) < 0)
{
swSysError("flock(%d, LOCK_SH) failed.", event->fd);
goto _error;
}
event->buf = sw_malloc(filesize);
if (event->buf == NULL)
{
goto _error;
}
int readn = swoole_sync_readfile(fd, event->buf, (int) filesize);
if (flock(fd, LOCK_UN) < 0)
{
swSysError("flock(%d, LOCK_UN) failed.", event->fd);
}
close(fd);
event->ret = readn;
event->error = 0;
}
static void swAio_handler_write_file(swAio_event *event)
{
int ret = -1;
int fd = open(event->req, event->flags, 0644);
if (fd < 0)
{
swSysError("open(%s, %d) failed.", (char * )event->req, event->flags);
event->ret = ret;
event->error = errno;
return;
}
if (flock(fd, LOCK_EX) < 0)
{
swSysError("flock(%d, LOCK_EX) failed.", event->fd);
event->ret = ret;
event->error = errno;
close(fd);
return;
}
int written = swoole_sync_writefile(fd, event->buf, event->nbytes);
if (event->flags & SW_AIO_WRITE_FSYNC)
{
if (fsync(fd) < 0)
{
swSysError("fsync(%d) failed.", event->fd);
}
}
if (flock(fd, LOCK_UN) < 0)
{
swSysError("flock(%d, LOCK_UN) failed.", event->fd);
}
close(fd);
event->ret = written;
event->error = 0;
}
static void swAio_handler_write(swAio_event *event)
{
int ret = -1;
if (flock(event->fd, LOCK_EX) < 0)
{
swSysError("flock(%d, LOCK_EX) failed.", event->fd);
return;
}
if (event->offset == 0)
{
ret = write(event->fd, event->buf, event->nbytes);
}
else
{
ret = pwrite(event->fd, event->buf, event->nbytes, event->offset);
}
if (event->flags & SW_AIO_WRITE_FSYNC)
{
if (fsync(event->fd) < 0)
{
swSysError("fsync(%d) failed.", event->fd);
}
}
if (flock(event->fd, LOCK_UN) < 0)
{
swSysError("flock(%d, LOCK_UN) failed.", event->fd);
}
event->ret = ret;
}
static void swAio_handler_gethostbyname(swAio_event *event)
{
struct in_addr addr_v4;
struct in6_addr addr_v6;
int ret;
#ifndef HAVE_GETHOSTBYNAME2_R
SwooleAIO.lock.lock(&SwooleAIO.lock);
#endif
if (event->flags == AF_INET6)
{
ret = swoole_gethostbyname(AF_INET6, event->buf, (char *) &addr_v6);
}
else
{
ret = swoole_gethostbyname(AF_INET, event->buf, (char *) &addr_v4);
}
bzero(event->buf, event->nbytes);
#ifndef HAVE_GETHOSTBYNAME2_R
SwooleAIO.lock.unlock(&SwooleAIO.lock);
#endif
if (ret < 0)
{
event->error = h_errno;
}
else
{
if (inet_ntop(event->flags == AF_INET6 ? AF_INET6 : AF_INET,
event->flags == AF_INET6 ? (void *) &addr_v6 : (void *) &addr_v4, event->buf, event->nbytes) == NULL)
{
ret = -1;
event->error = SW_ERROR_BAD_IPV6_ADDRESS;
}
else
{
event->error = 0;
ret = 0;
}
}
event->ret = ret;
}
static void swAio_handler_getaddrinfo(swAio_event *event)
{
swRequest_getaddrinfo *req = (swRequest_getaddrinfo *) event->req;
event->ret = swoole_getaddrinfo(req);
event->error = req->error;
}
static int swAioBase_thread_onTask(swThreadPool *pool, void *task, int task_len)
{
swAio_event *event = task;
if (event->type >= SW_AIO_HANDLER_MAX_SIZE || SwooleAIO.handlers[event->type] == NULL)
{
event->error = SW_ERROR_AIO_BAD_REQUEST;
event->ret = -1;
goto _error;
}
SwooleAIO.handlers[event->type](event);
swTrace("aio_thread ok. ret=%d, error=%d", event->ret, event->error);
_error: do
{
SwooleAIO.lock.lock(&SwooleAIO.lock);
int ret = write(swAioBase_pipe_write, &task, sizeof(task));
SwooleAIO.lock.unlock(&SwooleAIO.lock);
if (ret < 0)
{
if (errno == EAGAIN)
{
swYield();
continue;
}
else if (errno == EINTR)
{
continue;
}
else
{
swSysError("sendto swoole_aio_pipe_write failed.");
}
}
break;
} while (1);
return SW_OK;
}
static int swAioBase_write(int fd, void *inbuf, size_t size, off_t offset)
{
swAio_event *aio_ev = (swAio_event *) sw_malloc(sizeof(swAio_event));
if (aio_ev == NULL)
{
swWarn("malloc failed.");
return SW_ERR;
}
bzero(aio_ev, sizeof(swAio_event));
aio_ev->fd = fd;
aio_ev->buf = inbuf;
aio_ev->type = SW_AIO_WRITE;
aio_ev->nbytes = size;
aio_ev->offset = offset;
aio_ev->task_id = SwooleAIO.current_id++;
if (swThreadPool_dispatch(&swAioBase_thread_pool, aio_ev, sizeof(aio_ev)) < 0)
{
return SW_ERR;
}
else
{
SwooleAIO.task_num++;
return aio_ev->task_id;
}
}
int swAio_dns_lookup(void *hostname, void *ip_addr, size_t size)
{
swAio_event *aio_ev = (swAio_event *) sw_malloc(sizeof(swAio_event));
if (aio_ev == NULL)
{
swWarn("malloc failed.");
return SW_ERR;
}
bzero(aio_ev, sizeof(swAio_event));
aio_ev->buf = ip_addr;
aio_ev->req = hostname;
aio_ev->type = SW_AIO_GETHOSTBYNAME;
aio_ev->nbytes = size;
aio_ev->task_id = SwooleAIO.current_id++;
if (swThreadPool_dispatch(&swAioBase_thread_pool, aio_ev, sizeof(aio_ev)) < 0)
{
return SW_ERR;
}
else
{
SwooleAIO.task_num++;
return aio_ev->task_id;
}
}
int swAio_dispatch(swAio_event *_event)
{
if (SwooleAIO.init == 0)
{
swAio_init();
}
_event->task_id = SwooleAIO.current_id++;
swAio_event *event = (swAio_event *) sw_malloc(sizeof(swAio_event));
if (event == NULL)
{
swWarn("malloc failed.");
return SW_ERR;
}
memcpy(event, _event, sizeof(swAio_event));
if (swThreadPool_dispatch(&swAioBase_thread_pool, event, sizeof(event)) < 0)
{
return SW_ERR;
}
else
{
SwooleAIO.task_num++;
return _event->task_id;
}
}
static int swAioBase_read(int fd, void *inbuf, size_t size, off_t offset)
{
swAio_event *aio_ev = (swAio_event *) sw_malloc(sizeof(swAio_event));
if (aio_ev == NULL)
{
swWarn("malloc failed.");
return SW_ERR;
}
bzero(aio_ev, sizeof(swAio_event));
aio_ev->fd = fd;
aio_ev->buf = inbuf;
aio_ev->type = SW_AIO_READ;
aio_ev->nbytes = size;
aio_ev->offset = offset;
aio_ev->task_id = SwooleAIO.current_id++;
if (swThreadPool_dispatch(&swAioBase_thread_pool, aio_ev, sizeof(aio_ev)) < 0)
{
return SW_ERR;
}
else
{
SwooleAIO.task_num++;
return aio_ev->task_id;
}
}
void swAioBase_destroy()
{
swThreadPool_free(&swAioBase_thread_pool);
if (SwooleG.main_reactor)
{
SwooleG.main_reactor->del(SwooleG.main_reactor, swAioBase_pipe_read);
}
swoole_aio_pipe.close(&swoole_aio_pipe);
}

127
vendor/swoole/src/os/msg_queue.c vendored Executable file
View File

@ -0,0 +1,127 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int swMsgQueue_free(swMsgQueue *q)
{
if (msgctl(q->msg_id, IPC_RMID, 0) < 0)
{
swSysError("msgctl(%d, IPC_RMID) failed.", q->msg_id);
return SW_ERR;
}
return SW_OK;
}
void swMsgQueue_set_blocking(swMsgQueue *q, uint8_t blocking)
{
if (blocking == 0)
{
q->flags = q->flags | IPC_NOWAIT;
}
else
{
q->flags = q->flags & (~IPC_NOWAIT);
}
}
int swMsgQueue_create(swMsgQueue *q, int blocking, key_t msg_key, int perms)
{
if (perms <= 0 || perms >= 01000)
{
perms = 0666;
}
int msg_id;
msg_id = msgget(msg_key, IPC_CREAT | perms);
if (msg_id < 0)
{
swSysError("msgget() failed.");
return SW_ERR;
}
else
{
bzero(q, sizeof(swMsgQueue));
q->msg_id = msg_id;
q->perms = perms;
q->blocking = blocking;
swMsgQueue_set_blocking(q, blocking);
}
return 0;
}
int swMsgQueue_pop(swMsgQueue *q, swQueue_data *data, int length)
{
int ret = msgrcv(q->msg_id, data, length, data->mtype, q->flags);
if (ret < 0)
{
SwooleG.error = errno;
if (errno != ENOMSG && errno != EINTR)
{
swSysError("msgrcv(%d, %d, %ld) failed.", q->msg_id, length, data->mtype);
}
}
return ret;
}
int swMsgQueue_push(swMsgQueue *q, swQueue_data *in, int length)
{
int ret;
while (1)
{
ret = msgsnd(q->msg_id, in, length, q->flags);
if (ret < 0)
{
SwooleG.error = errno;
if (errno == EINTR)
{
continue;
}
else if (errno == EAGAIN)
{
return -1;
}
else
{
swSysError("msgsnd(%d, %d, %ld) failed.", q->msg_id, length, in->mtype);
return -1;
}
}
else
{
return ret;
}
}
return 0;
}
int swMsgQueue_stat(swMsgQueue *q, int *queue_num, int *queue_bytes)
{
struct msqid_ds __stat;
if (msgctl(q->msg_id, IPC_STAT, &__stat) == 0)
{
*queue_num = __stat.msg_qnum;
*queue_bytes = __stat.msg_cbytes;
return 0;
}
else
{
return -1;
}
}

101
vendor/swoole/src/os/sendfile.c vendored Executable file
View File

@ -0,0 +1,101 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
#ifdef HAVE_KQUEUE
#include <sys/uio.h>
int swoole_sendfile(int out_fd, int in_fd, off_t *offset, size_t size)
{
off_t sent_bytes = 0;
int ret;
#ifdef __MACH__
struct sf_hdtr hdtr;
hdtr.headers = NULL;
hdtr.hdr_cnt = 0;
hdtr.trailers = NULL;
hdtr.trl_cnt = 0;
#endif
//sent_bytes = (off_t)size;
swTrace("send file, out_fd:%d, in_fd:%d, offset:%ld, size:%ld", out_fd, in_fd, (long)*offset, (long)size);
do_sendfile:
#ifdef __MACH__
ret = sendfile(in_fd, out_fd, *offset, (long long *) &size, &hdtr, 0);
#else
ret = sendfile(in_fd, out_fd, *offset, size, 0, &sent_bytes, 0);
#endif
if (ret == -1)
{
if (errno == EAGAIN)
{
*offset += sent_bytes;
return sent_bytes;
}
else if (errno == EINTR)
{
goto do_sendfile;
}
else
{
return -1;
}
}
else if (ret == 0)
{
*offset += size;
return size;
}
else
{
swWarn("sendfile failed. Error: %s[%d]", strerror(errno), errno);
return SW_ERR;
}
return SW_OK;
}
#elif !defined(HAVE_SENDFILE)
int swoole_sendfile(int out_fd, int in_fd, off_t *offset, size_t size)
{
char buf[SW_BUFFER_SIZE_BIG];
int readn = size > sizeof(buf) ? sizeof(buf) : size;
int ret;
int n = pread(in_fd, buf, readn, *offset);
if (n > 0)
{
ret = write(out_fd, buf, n);
if (ret < 0)
{
swSysError("write() failed.");
}
else
{
*offset += ret;
}
return ret;
}
else
{
swSysError("pread() failed.");
return SW_ERR;
}
}
#endif

262
vendor/swoole/src/os/signal.c vendored Executable file
View File

@ -0,0 +1,262 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
#ifdef HAVE_SIGNALFD
#include <sys/signalfd.h>
static void swSignalfd_set(int signo, swSignalHander callback);
static void swSignalfd_clear();
static int swSignalfd_onSignal(swReactor *reactor, swEvent *event);
static sigset_t signalfd_mask;
static int signal_fd = 0;
#endif
typedef struct
{
swSignalHander callback;
uint16_t signo;
uint16_t active;
} swSignal;
static swSignal signals[SW_SIGNO_MAX];
static int _lock = 0;
static void swSignal_async_handler(int signo);
/**
* clear all singal
*/
void swSignal_none(void)
{
sigset_t mask;
sigfillset(&mask);
int ret = pthread_sigmask(SIG_BLOCK, &mask, NULL);
if (ret < 0)
{
swWarn("pthread_sigmask() failed. Error: %s[%d]", strerror(ret), ret);
}
}
/**
* setup signal
*/
swSignalHander swSignal_set(int sig, swSignalHander func, int restart, int mask)
{
//ignore
if (func == NULL)
{
func = SIG_IGN;
}
//clear
else if ((long) func == -1)
{
func = SIG_DFL;
}
struct sigaction act, oact;
act.sa_handler = func;
if (mask)
{
sigfillset(&act.sa_mask);
}
else
{
sigemptyset(&act.sa_mask);
}
act.sa_flags = 0;
if (sigaction(sig, &act, &oact) < 0)
{
return NULL;
}
return oact.sa_handler;
}
void swSignal_add(int signo, swSignalHander func)
{
#ifdef HAVE_SIGNALFD
if (SwooleG.use_signalfd)
{
swSignalfd_set(signo, func);
}
else
#endif
{
signals[signo].callback = func;
signals[signo].active = 1;
signals[signo].signo = signo;
swSignal_set(signo, swSignal_async_handler, 1, 0);
}
}
static void swSignal_async_handler(int signo)
{
if (SwooleG.main_reactor)
{
SwooleG.main_reactor->singal_no = signo;
}
else
{
//discard signal
if (_lock)
{
return;
}
_lock = 1;
swSignal_callback(signo);
_lock = 0;
}
}
void swSignal_callback(int signo)
{
if (signo >= SW_SIGNO_MAX)
{
swWarn("signal[%d] numberis invalid.", signo);
return;
}
swSignalHander callback = signals[signo].callback;
if (!callback)
{
swWarn("signal[%d] callback is null.", signo);
return;
}
callback(signo);
}
void swSignal_clear(void)
{
#ifdef HAVE_SIGNALFD
if (SwooleG.use_signalfd)
{
swSignalfd_clear();
}
else
#endif
{
int i;
for (i = 0; i < SW_SIGNO_MAX; i++)
{
if (signals[i].active)
{
swSignal_set(signals[i].signo, (swSignalHander) -1, 1, 0);
}
}
}
bzero(&signals, sizeof(signals));
}
#ifdef HAVE_SIGNALFD
void swSignalfd_init()
{
sigemptyset(&signalfd_mask);
bzero(&signals, sizeof(signals));
}
static void swSignalfd_set(int signo, swSignalHander callback)
{
if (callback == NULL && signals[signo].active)
{
sigdelset(&signalfd_mask, signo);
bzero(&signals[signo], sizeof(swSignal));
}
else
{
sigaddset(&signalfd_mask, signo);
signals[signo].callback = callback;
signals[signo].signo = signo;
signals[signo].active = 1;
}
if (signal_fd > 0)
{
sigprocmask(SIG_BLOCK, &signalfd_mask, NULL);
signalfd(signal_fd, &signalfd_mask, SFD_NONBLOCK | SFD_CLOEXEC);
}
}
int swSignalfd_setup(swReactor *reactor)
{
if (signal_fd == 0)
{
signal_fd = signalfd(-1, &signalfd_mask, SFD_NONBLOCK | SFD_CLOEXEC);
if (signal_fd < 0)
{
swWarn("signalfd() failed. Error: %s[%d]", strerror(errno), errno);
return SW_ERR;
}
SwooleG.signal_fd = signal_fd;
if (sigprocmask(SIG_BLOCK, &signalfd_mask, NULL) == -1)
{
swWarn("sigprocmask() failed. Error: %s[%d]", strerror(errno), errno);
return SW_ERR;
}
reactor->setHandle(reactor, SW_FD_SIGNAL, swSignalfd_onSignal);
reactor->add(reactor, signal_fd, SW_FD_SIGNAL);
return SW_OK;
}
else
{
swWarn("signalfd has been created");
return SW_ERR;
}
}
static void swSignalfd_clear()
{
if (signal_fd)
{
if (sigprocmask(SIG_UNBLOCK, &signalfd_mask, NULL) < 0)
{
swSysError("sigprocmask(SIG_UNBLOCK) failed.");
}
close(signal_fd);
bzero(&signalfd_mask, sizeof(signalfd_mask));
}
signal_fd = 0;
}
static int swSignalfd_onSignal(swReactor *reactor, swEvent *event)
{
int n;
struct signalfd_siginfo siginfo;
n = read(event->fd, &siginfo, sizeof(siginfo));
if (n < 0)
{
swWarn("read from signalfd failed. Error: %s[%d]", strerror(errno), errno);
return SW_OK;
}
if (siginfo.ssi_signo >= SW_SIGNO_MAX)
{
swWarn("unknown signal[%d].", siginfo.ssi_signo);
return SW_OK;
}
if (signals[siginfo.ssi_signo].active)
{
if (signals[siginfo.ssi_signo].callback)
{
signals[siginfo.ssi_signo].callback(siginfo.ssi_signo);
}
else
{
swWarn("signal[%d] callback is null.", siginfo.ssi_signo);
}
}
return SW_OK;
}
#endif

240
vendor/swoole/src/os/timer.c vendored Executable file
View File

@ -0,0 +1,240 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
#include "Server.h"
#ifdef HAVE_TIMERFD
#include <sys/timerfd.h>
#endif
static int swSystemTimer_signal_set(swTimer *timer, long interval);
static int swSystemTimer_timerfd_set(swTimer *timer, long interval);
static int swSystemTimer_set(swTimer *timer, long new_interval);
/**
* create timer
*/
int swSystemTimer_init(int interval, int use_pipe)
{
swTimer *timer = &SwooleG.timer;
timer->lasttime = interval;
#ifndef HAVE_TIMERFD
SwooleG.use_timerfd = 0;
#endif
if (SwooleG.use_timerfd)
{
if (swSystemTimer_timerfd_set(timer, interval) < 0)
{
return SW_ERR;
}
timer->use_pipe = 0;
}
else
{
if (use_pipe)
{
if (swPipeNotify_auto(&timer->pipe, 0, 0) < 0)
{
return SW_ERR;
}
timer->fd = timer->pipe.getFd(&timer->pipe, 0);
timer->use_pipe = 1;
}
else
{
timer->fd = 1;
timer->use_pipe = 0;
}
if (swSystemTimer_signal_set(timer, interval) < 0)
{
return SW_ERR;
}
swSignal_add(SIGALRM, swSystemTimer_signal_handler);
}
if (timer->fd > 1)
{
SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_TIMER, swSystemTimer_event_handler);
SwooleG.main_reactor->add(SwooleG.main_reactor, SwooleG.timer.fd, SW_FD_TIMER);
}
timer->set = swSystemTimer_set;
return SW_OK;
}
/**
* timerfd
*/
static int swSystemTimer_timerfd_set(swTimer *timer, long interval)
{
#ifdef HAVE_TIMERFD
struct timeval now;
int sec = interval / 1000;
int msec = (((float) interval / 1000) - sec) * 1000;
if (gettimeofday(&now, NULL) < 0)
{
swWarn("gettimeofday() failed. Error: %s[%d]", strerror(errno), errno);
return SW_ERR;
}
struct itimerspec timer_set;
bzero(&timer_set, sizeof(timer_set));
if (interval < 0)
{
if (timer->fd == 0)
{
return SW_OK;
}
}
else
{
timer_set.it_interval.tv_sec = sec;
timer_set.it_interval.tv_nsec = msec * 1000 * 1000;
timer_set.it_value.tv_sec = now.tv_sec + sec;
timer_set.it_value.tv_nsec = (now.tv_usec * 1000) + timer_set.it_interval.tv_nsec;
if (timer_set.it_value.tv_nsec > 1e9)
{
timer_set.it_value.tv_nsec = timer_set.it_value.tv_nsec - 1e9;
timer_set.it_value.tv_sec += 1;
}
if (timer->fd == 0)
{
timer->fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC);
if (timer->fd < 0)
{
swWarn("timerfd_create() failed. Error: %s[%d]", strerror(errno), errno);
return SW_ERR;
}
}
}
if (timerfd_settime(timer->fd, TFD_TIMER_ABSTIME, &timer_set, NULL) == -1)
{
swWarn("timerfd_settime() failed. Error: %s[%d]", strerror(errno), errno);
return SW_ERR;
}
return SW_OK;
#else
swWarn("kernel not support timerfd.");
return SW_ERR;
#endif
}
/**
* setitimer
*/
static int swSystemTimer_signal_set(swTimer *timer, long interval)
{
struct itimerval timer_set;
int sec = interval / 1000;
int msec = (((float) interval / 1000) - sec) * 1000;
struct timeval now;
if (gettimeofday(&now, NULL) < 0)
{
swWarn("gettimeofday() failed. Error: %s[%d]", strerror(errno), errno);
return SW_ERR;
}
bzero(&timer_set, sizeof(timer_set));
if (interval > 0)
{
timer_set.it_interval.tv_sec = sec;
timer_set.it_interval.tv_usec = msec * 1000;
timer_set.it_value.tv_sec = sec;
timer_set.it_value.tv_usec = timer_set.it_interval.tv_usec;
if (timer_set.it_value.tv_usec > 1e6)
{
timer_set.it_value.tv_usec = timer_set.it_value.tv_usec - 1e6;
timer_set.it_value.tv_sec += 1;
}
}
if (setitimer(ITIMER_REAL, &timer_set, NULL) < 0)
{
swWarn("setitimer() failed. Error: %s[%d]", strerror(errno), errno);
return SW_ERR;
}
return SW_OK;
}
void swSystemTimer_free(swTimer *timer)
{
if (timer->use_pipe)
{
timer->pipe.close(&timer->pipe);
}
else if (timer->fd > 2)
{
if (close(timer->fd) < 0)
{
swSysError("close(%d) failed.", timer->fd);
}
}
}
static long current_interval = 0;
static int swSystemTimer_set(swTimer *timer, long new_interval)
{
if (new_interval == current_interval)
{
return SW_OK;
}
current_interval = new_interval;
if (SwooleG.use_timerfd)
{
return swSystemTimer_timerfd_set(timer, new_interval);
}
else
{
return swSystemTimer_signal_set(timer, new_interval);
}
}
int swSystemTimer_event_handler(swReactor *reactor, swEvent *event)
{
uint64_t exp;
swTimer *timer = &SwooleG.timer;
if (read(timer->fd, &exp, sizeof(uint64_t)) != sizeof(uint64_t))
{
return SW_ERR;
}
SwooleG.signal_alarm = 0;
return swTimer_select(timer);
}
void swSystemTimer_signal_handler(int sig)
{
SwooleG.signal_alarm = 1;
uint64_t flag = 1;
if (SwooleG.timer.use_pipe)
{
SwooleG.timer.pipe.write(&SwooleG.timer.pipe, &flag, sizeof(flag));
}
}