예제 #1
0
파일: Port.c 프로젝트: gfxmotion/swoole-src
int swPort_listen(swListenPort *ls)
{
    if (swSocket_is_dgram(ls->type))
    {
        int sock = swSocket_listen(ls->type, ls->host, ls->port, ls->backlog);
        if (sock < 0)
        {
            return SW_ERR;
        }

        int bufsize = SwooleG.socket_buffer_size;
        setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
        setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
        ls->sock = sock;
        return sock;
    }

#ifdef SW_USE_OPENSSL
    if (ls->open_ssl_encrypt)
    {
        if (ls->ssl_cert_file == NULL || ls->ssl_key_file == NULL)
        {
            swWarn("SSL error, require ssl_cert_file and ssl_key_file.");
            return SW_ERR;
        }
        ls->ssl_context = swSSL_get_context(ls->ssl_method, ls->ssl_cert_file, ls->ssl_key_file);
        if (ls->ssl_context == NULL)
        {
            return SW_ERR;
        }
        if (ls->ssl_client_cert_file && swSSL_set_client_certificate(ls->ssl_context, ls->ssl_client_cert_file, ls->ssl_verify_depth) == SW_ERR)
        {
            return SW_ERR;
        }
    }

    if (ls->ssl)
    {
        if (!ls->ssl_cert_file)
        {
            swWarn("need to configure [server->ssl_cert_file].");
            return SW_ERR;
        }
        if (!ls->ssl_key_file)
        {
            swWarn("need to configure [server->ssl_key_file].");
            return SW_ERR;
        }
    }
#endif

    //TCP
    int sock = swSocket_listen(ls->type, ls->host, ls->port, ls->backlog);
    if (sock < 0)
    {
        return SW_ERR;
    }

#ifdef TCP_DEFER_ACCEPT
    if (ls->tcp_defer_accept)
    {
        if (setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, (const void*) &ls->tcp_defer_accept, sizeof(int)) < 0)
        {
            swSysError("setsockopt(TCP_DEFER_ACCEPT) failed.");
        }
    }
#endif

#ifdef TCP_FASTOPEN
    if (ls->tcp_fastopen)
    {
        if (setsockopt(sock, IPPROTO_TCP, TCP_FASTOPEN, (const void*) &ls->tcp_fastopen, sizeof(int)) < 0)
        {
            swSysError("setsockopt(TCP_FASTOPEN) failed.");
        }
    }
#endif

#ifdef SO_KEEPALIVE
    int sockopt;
    if (ls->open_tcp_keepalive == 1)
    {
        sockopt = 1;
        if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &sockopt, sizeof(int)) < 0)
        {
            swSysError("setsockopt(SO_KEEPALIVE) failed.");
        }
#ifdef TCP_KEEPIDLE
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, (void*) &ls->tcp_keepidle, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, (void *) &ls->tcp_keepinterval, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, (void *) &ls->tcp_keepcount, sizeof(int));
#endif
    }
#endif
    return sock;
}
예제 #2
0
파일: base.c 프로젝트: yangxikun/swoole-src
static int swAioBase_thread_onTask(swThreadPool *pool, void *task, int task_len)
{
    swAio_event *event = task;
    struct in_addr addr;

    char *ip_addr;
    int ret = -1;

    start_switch:
    switch(event->type)
    {
    case SW_AIO_WRITE:
        if (flock(event->fd, LOCK_EX) < 0)
        {
            swSysError("flock(%d, LOCK_EX) failed.", event->fd);
            break;
        }
        if (event->offset == 0)
        {
            ret = write(event->fd, event->buf, event->nbytes);
        }
        else
        {
            ret = pwrite(event->fd, event->buf, event->nbytes, event->offset);
        }
#if 0
        if (fsync(event->fd) < 0)
        {
            swSysError("fsync(%d) failed.", event->fd);
        }
#endif
        if (flock(event->fd, LOCK_UN) < 0)
        {
            swSysError("flock(%d, LOCK_UN) failed.", event->fd);
        }
        break;
    case SW_AIO_READ:
        if (flock(event->fd, LOCK_SH) < 0)
        {
            swSysError("flock(%d, LOCK_SH) failed.", event->fd);
            break;
        }
        ret = pread(event->fd, event->buf, event->nbytes, event->offset);
        if (flock(event->fd, LOCK_UN) < 0)
        {
            swSysError("flock(%d, LOCK_UN) failed.", event->fd);
        }
        break;
    case SW_AIO_DNS_LOOKUP:
        ret = swoole_gethostbyname(event->flags == AF_INET6 ? AF_INET6 : AF_INET, event->buf, (char *) &addr);
        if (ret < 0)
        {
            event->error = h_errno;
            switch (h_errno)
            {
            case HOST_NOT_FOUND:
                bzero(event->buf, event->nbytes);
                ret = 0;
                break;
            default:
                ret = -1;
                break;
            }
        }
        else
        {
            ip_addr = inet_ntoa(addr);
            bzero(event->buf, event->nbytes);
            memcpy(event->buf, ip_addr, strnlen(ip_addr, SW_IP_MAX_LENGTH) + 1);
            ret = 0;
        }
        break;
    default:
        swWarn("unknow aio task.");
        break;
    }

    event->ret = ret;
    if (ret < 0)
    {
        if (errno == EINTR || errno == EAGAIN)
        {
            goto start_switch;
        }
        else
        {
            event->error = errno;
        }
    }

    swTrace("aio_thread ok. ret=%d", ret);
    do
    {
        SwooleAIO.lock.lock(&SwooleAIO.lock);
        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
            {
                swWarn("sendto swoole_aio_pipe_write failed. Error: %s[%d]", strerror(errno), errno);
            }
        }
        break;
    } while(1);

    return SW_OK;
}
예제 #3
0
파일: Worker.c 프로젝트: netroby/swoole-src
void swWorker_onStart(swServer *serv)
{
    /**
     * Release other worker process
     */
    swWorker *worker;

    if (SwooleWG.id >= serv->worker_num)
    {
        SwooleG.process_type = SW_PROCESS_TASKWORKER;
    }
    else
    {
        SwooleG.process_type = SW_PROCESS_WORKER;
    }

    int is_root = !geteuid();
    struct passwd *passwd = NULL;
    struct group *group = NULL;

    if (is_root)
    {
        //get group info
        if (SwooleG.group)
        {
            group = getgrnam(SwooleG.group);
            if (!group)
            {
                swWarn("get group [%s] info failed.", SwooleG.group);
            }
        }
        //get user info
        if (SwooleG.user)
        {
            passwd = getpwnam(SwooleG.user);
            if (!passwd)
            {
                swWarn("get user [%s] info failed.", SwooleG.user);
            }
        }
        //chroot
        if (SwooleG.chroot)
        {
            if (0 > chroot(SwooleG.chroot))
            {
                swSysError("chroot to [%s] failed.", SwooleG.chroot);
            }
        }
        //set process group
        if (SwooleG.group && group)
        {
            if (setgid(group->gr_gid) < 0)
            {
                swSysError("setgid to [%s] failed.", SwooleG.group);
            }
        }
        //set process user
        if (SwooleG.user && passwd)
        {
            if (setuid(passwd->pw_uid) < 0)
            {
                swSysError("setuid to [%s] failed.", SwooleG.user);
            }
        }
    }

    SwooleWG.worker = swServer_get_worker(serv, SwooleWG.id);

    int i;
    for (i = 0; i < serv->worker_num + SwooleG.task_worker_num; i++)
    {
        worker = swServer_get_worker(serv, i);
        if (SwooleWG.id == i)
        {
            continue;
        }
        else
        {
            swWorker_free(worker);
        }
        if (swIsWorker())
        {
            swSetNonBlock(worker->pipe_master);
        }
    }

    if (serv->onWorkerStart)
    {
        serv->onWorkerStart(serv, SwooleWG.id);
    }
}
예제 #4
0
파일: Port.c 프로젝트: gfxmotion/swoole-src
/**
 * For Http Protocol
 */
static int swPort_onRead_http(swReactor *reactor, swListenPort *port, swEvent *event)
{
    swConnection *conn = event->socket;

#ifdef SW_USE_OPENSSL
    if (swPort_check_ssl_state(port, conn) < 0)
    {
        goto close_fd;
    }
#endif

    if (conn->websocket_status >= WEBSOCKET_STATUS_HANDSHAKE)
    {
        if (conn->object != NULL)
        {
            swHttpRequest_free(conn);
            conn->websocket_status = WEBSOCKET_STATUS_ACTIVE;
        }
        return swPort_onRead_check_length(reactor, port, event);
    }

    int n = 0;
    char *buf;
    int buf_len;

    swHttpRequest *request = NULL;
    swProtocol *protocol = &port->protocol;

    //new http request
    if (conn->object == NULL)
    {
        request = sw_malloc(sizeof(swHttpRequest));
        bzero(request, sizeof(swHttpRequest));
        conn->object = request;
    }
    else
    {
        request = (swHttpRequest *) conn->object;
    }

    if (!request->buffer)
    {
        request->buffer = swString_new(SW_HTTP_HEADER_MAX_SIZE);
        //alloc memory failed.
        if (!request->buffer)
        {
            swReactorThread_onClose(reactor, event);
            return SW_ERR;
        }
    }

    swString *buffer = request->buffer;

    recv_data:
    buf = buffer->str + buffer->length;
    buf_len = buffer->size - buffer->length;

    n = swConnection_recv(conn, buf, buf_len, 0);
    if (n < 0)
    {
        switch (swConnection_error(errno))
        {
        case SW_ERROR:
            swSysError("recv from connection#%d failed.", event->fd);
            return SW_OK;
        case SW_CLOSE:
            goto close_fd;
        default:
            return SW_OK;
        }
    }
    else if (n == 0)
    {
        close_fd:
        swHttpRequest_free(conn);
        swReactorThread_onClose(reactor, event);
        return SW_OK;
    }
    else
    {
        conn->last_time = SwooleGS->now;
        buffer->length += n;

        if (request->method == 0 && swHttpRequest_get_protocol(request) < 0)
        {
            if (request->buffer->length < SW_HTTP_HEADER_MAX_SIZE)
            {
                return SW_OK;
            }

            swWarn("get protocol failed.");
#ifdef SW_HTTP_BAD_REQUEST
            if (swConnection_send(conn, SW_STRL(SW_HTTP_BAD_REQUEST) - 1, 0) < 0)
            {
                swSysError("send() failed.");
            }
#endif
            goto close_fd;
        }

        swTrace("request->method=%d", request->method);

        //DELETE
        if (request->method == HTTP_DELETE)
        {
            if (request->content_length == 0 && swHttpRequest_have_content_length(request) == SW_FALSE)
            {
                goto http_no_entity;
            }
            else
            {
                goto http_entity;
            }
        }
        //GET HEAD OPTIONS
        else if (request->method == HTTP_GET || request->method == HTTP_HEAD || request->method == HTTP_OPTIONS)
        {
            http_no_entity:
            if (memcmp(buffer->str + buffer->length - 4, "\r\n\r\n", 4) == 0)
            {
                swReactorThread_dispatch(conn, buffer->str, buffer->length);
                swHttpRequest_free(conn);
            }
            else if (buffer->size == buffer->length)
            {
                swWarn("http header is too long.");
                goto close_fd;
            }
            //wait more data
            else
            {
                goto recv_data;
            }
        }
        //POST PUT HTTP_PATCH
        else if (request->method == HTTP_POST || request->method == HTTP_PUT || request->method == HTTP_PATCH)
        {
            http_entity:
            if (request->content_length == 0)
            {
                if (swHttpRequest_get_content_length(request) < 0)
                {
                    if (buffer->size == buffer->length)
                    {
                        swWarn("http header is too long.");
                        goto close_fd;
                    }
                    else
                    {
                        goto recv_data;
                    }
                }
                else if (request->content_length > protocol->package_max_length)
                {
                    swWarn("content-length more than the package_max_length[%d].", protocol->package_max_length);
                    goto close_fd;
                }
            }

            uint32_t request_size = 0;

            //http header is not the end
            if (request->header_length == 0)
            {
                if (buffer->size == buffer->length)
                {
                    swWarn("http header is too long.");
                    goto close_fd;
                }
                if (swHttpRequest_get_header_length(request) < 0)
                {
                    goto recv_data;
                }
                request_size = request->content_length + request->header_length;
            }
            else
            {
                request_size = request->content_length + request->header_length;
            }

            if (request_size > buffer->size && swString_extend(buffer, request_size) < 0)
            {
                goto close_fd;
            }

            //discard the redundant data
            if (buffer->length > request_size)
            {
                buffer->length = request_size;
            }

            if (buffer->length == request_size)
            {
                swReactorThread_dispatch(conn, buffer->str, buffer->length);
                swHttpRequest_free(conn);
            }
            else
            {
#ifdef SW_HTTP_100_CONTINUE
                //Expect: 100-continue
                if (swHttpRequest_has_expect_header(request))
                {
                    swSendData _send;
                    _send.data = "HTTP/1.1 100 Continue\r\n\r\n";
                    _send.length = strlen(_send.data);

                    int send_times = 0;
                    direct_send:
                    n = swConnection_send(conn, _send.data, _send.length, 0);
                    if (n < _send.length)
                    {
                        _send.data += n;
                        _send.length -= n;
                        send_times++;
                        if (send_times < 10)
                        {
                            goto direct_send;
                        }
                        else
                        {
                            swWarn("send http header failed");
                        }
                    }
                }
                else
                {
                    swTrace("PostWait: request->content_length=%d, buffer->length=%zd, request->header_length=%d\n",
                            request->content_length, buffer->length, request->header_length);
                }
#endif
                goto recv_data;
            }
        }
        else
        {
            swWarn("method no support");
            goto close_fd;
        }
    }
    return SW_OK;
}
예제 #5
0
/**
 * @return SW_ERR: close the connection
 * @return SW_OK: continue
 */
int swProtocol_recv_check_length(swProtocol *protocol, swConnection *conn, swString *buffer)
{
    int package_length;
    uint32_t recv_size;
    char swap[SW_BUFFER_SIZE];

    do_recv:
    if (buffer->offset > 0)
    {
        recv_size = buffer->offset - buffer->length;
    }
    else
    {
        recv_size = protocol->package_length_offset + protocol->package_length_size;
    }

    int ret = swConnection_recv(conn, buffer->str + buffer->length, recv_size, 0);
    if (ret < 0)
    {
        switch (swConnection_error(errno))
        {
        case SW_ERROR:
            swSysError("recv(%d, %d) failed.", conn->fd, recv_size);
            return SW_OK;
        case SW_CLOSE:
            conn->close_errno = errno;
            return SW_ERR;
        default:
            return SW_OK;
        }
    }
    else if (ret == 0)
    {
        return SW_ERR;
    }
    else
    {
        buffer->length += ret;

        if (conn->recv_wait)
        {
            if (buffer->length >= buffer->offset)
            {
                do_dispatch:
                ret = protocol->onPackage(conn, buffer->str, buffer->offset);
                conn->recv_wait = 0;

                int remaining_length = buffer->length - buffer->offset;
                if (remaining_length > 0)
                {
                    assert(remaining_length < sizeof(swap));
                    memcpy(swap, buffer->str + buffer->offset, remaining_length);
                    memcpy(buffer->str, swap, remaining_length);
                    buffer->offset = 0;
                    buffer->length = remaining_length;
                    goto do_get_length;
                }
                else
                {
                    swString_clear(buffer);
                    goto do_recv;
                }
            }
            else
            {
                return SW_OK;
            }
        }
        else
        {
            do_get_length: package_length = protocol->get_package_length(protocol, conn, buffer->str, buffer->length);
            //invalid package, close connection.
            if (package_length < 0)
            {
                return SW_ERR;
            }
            //no length
            else if (package_length == 0)
            {
                return SW_OK;
            }
            else if (package_length > protocol->package_max_length)
            {
                swWarn("package is too big, remote_addr=%s:%d, length=%d.", swConnection_get_ip(conn), swConnection_get_port(conn), package_length);
                return SW_ERR;
            }
            //get length success
            else
            {
                if (buffer->size < package_length)
                {
                    if (swString_extend(buffer, package_length) < 0)
                    {
                        return SW_ERR;
                    }
                }
                conn->recv_wait = 1;
                buffer->offset = package_length;

                if (buffer->length >= package_length)
                {
                    goto do_dispatch;
                }
                else
                {
                    goto do_recv;
                }
            }
        }
    }
    return SW_OK;
}
예제 #6
0
/**
 * @return SW_ERR: close the connection
 * @return SW_OK: continue
 */
int swProtocol_recv_check_eof(swProtocol *protocol, swConnection *conn, swString *buffer)
{
    int recv_again = SW_FALSE;
    int buf_size;

    recv_data: buf_size = buffer->size - buffer->length;
    char *buf_ptr = buffer->str + buffer->length;

    if (buf_size > SW_BUFFER_SIZE)
    {
        buf_size = SW_BUFFER_SIZE;
    }

    int n = swConnection_recv(conn, buf_ptr, buf_size, 0);
    //swNotice("ReactorThread: recv[len=%d]", n);
    if (n < 0)
    {
        switch (swConnection_error(errno))
        {
        case SW_ERROR:
            swSysError("recv from socket#%d failed.", conn->fd);
            return SW_OK;
        case SW_CLOSE:
            conn->close_errno = errno;
            return SW_ERR;
        default:
            return SW_OK;
        }
    }
    else if (n == 0)
    {
        return SW_ERR;
    }
    else
    {
        buffer->length += n;

        if (buffer->length < protocol->package_eof_len)
        {
            return SW_OK;
        }

        if (protocol->split_by_eof)
        {
            if (swProtocol_split_package_by_eof(protocol, conn, buffer) == 0)
            {
                return SW_OK;
            }
            else
            {
                recv_again = SW_TRUE;
            }
        }
        else if (memcmp(buffer->str + buffer->length - protocol->package_eof_len, protocol->package_eof, protocol->package_eof_len) == 0)
        {
            protocol->onPackage(conn, buffer->str, buffer->length);
            swString_clear(buffer);
            return SW_OK;
        }

        //over max length, will discard
        if (buffer->length == protocol->package_max_length)
        {
            swWarn("Package is too big. package_length=%d", (int )buffer->length);
            return SW_ERR;
        }

        //buffer is full, may have not read data
        if (buffer->length == buffer->size)
        {
            recv_again = SW_TRUE;
            if (buffer->size < protocol->package_max_length)
            {
                uint32_t extend_size = swoole_size_align(buffer->size * 2, SwooleG.pagesize);
                if (extend_size > protocol->package_max_length)
                {
                    extend_size = protocol->package_max_length;
                }
                if (swString_extend(buffer, extend_size) < 0)
                {
                    return SW_ERR;
                }
            }
        }
        //no eof
        if (recv_again)
        {
            goto recv_data;
        }
    }
    return SW_OK;
}
예제 #7
0
static int swClient_onStreamRead(swReactor *reactor, swEvent *event)
{
    int n;
    swClient *cli = event->socket->object;
    char *buf = cli->buffer->str + cli->buffer->length;
    long buf_size = cli->buffer->size - cli->buffer->length;

    if (cli->http_proxy && cli->http_proxy->state != SW_HTTP_PROXY_STATE_READY)
    {
#ifdef SW_USE_OPENSSL
        if (cli->open_ssl)
        {
            int n = swConnection_recv(event->socket, buf, buf_size, 0);
            if (n <= 0)
            {
                goto __close;
            }
            cli->buffer->length += n;
            if (cli->buffer->length < sizeof(SW_HTTPS_PROXY_HANDSHAKE_RESPONSE) - 1)
            {
                return SW_OK;
            }
            if (swClient_https_proxy_handshake(cli) < 0)
            {
                swoole_error_log(SW_LOG_NOTICE, SW_ERROR_HTTP_PROXY_HANDSHAKE_ERROR, "failed to handshake with http proxy.");
                goto connect_fail;
            }
            else
            {
                cli->http_proxy->state = SW_HTTP_PROXY_STATE_READY;
                swString_clear(cli->buffer);
            }
            if (swClient_enable_ssl_encrypt(cli) < 0)
            {
                goto connect_fail;
            }
            else
            {
                if (swClient_ssl_handshake(cli) < 0)
                {
                    goto connect_fail;
                }
                else
                {
                    cli->socket->ssl_state = SW_SSL_STATE_WAIT_STREAM;
                }
                return SwooleG.main_reactor->set(SwooleG.main_reactor, event->fd, SW_FD_STREAM_CLIENT | SW_EVENT_WRITE);
            }
            if (cli->onConnect)
            {
                execute_onConnect(cli);
            }
            return SW_OK;
        }
#endif
    }
    if (cli->socks5_proxy && cli->socks5_proxy->state != SW_SOCKS5_STATE_READY)
    {
        int n = swConnection_recv(event->socket, buf, buf_size, 0);
        if (n <= 0)
        {
            goto __close;
        }
        if (swSocks5_connect(cli, buf, buf_size) < 0)
        {
            goto __close;
        }
        if (cli->socks5_proxy->state != SW_SOCKS5_STATE_READY)
        {
            return SW_OK;
        }
#ifdef SW_USE_OPENSSL
        if (cli->open_ssl)
        {
            if (swClient_enable_ssl_encrypt(cli) < 0)
            {
                connect_fail:
                cli->socket->active = 0;
                cli->close(cli);
                if (cli->onError)
                {
                    cli->onError(cli);
                }
            }
            else
            {
                if (swClient_ssl_handshake(cli) < 0)
                {
                    goto connect_fail;
                }
                else
                {
                    cli->socket->ssl_state = SW_SSL_STATE_WAIT_STREAM;
                }
                return SwooleG.main_reactor->set(SwooleG.main_reactor, event->fd, SW_FD_STREAM_CLIENT | SW_EVENT_WRITE);
            }
        }
        else
#endif
        {
            if (cli->onConnect)
            {
                execute_onConnect(cli);
            }
        }
        return SW_OK;
    }

#ifdef SW_USE_OPENSSL
    if (cli->open_ssl && cli->socket->ssl_state == SW_SSL_STATE_WAIT_STREAM)
    {
        if (swClient_ssl_handshake(cli) < 0)
        {
            return cli->close(cli);
        }
        if (cli->socket->ssl_state != SW_SSL_STATE_READY)
        {
            return SW_OK;
        }
        //ssl handshake sucess
        else if (cli->onConnect)
        {
            execute_onConnect(cli);
        }
    }
#endif

    /**
     * redirect stream data to other socket
     */
    if (cli->redirect)
    {
        int ret = 0;
        n = swConnection_recv(event->socket, buf, buf_size, 0);
        if (n < 0)
        {
            goto __error;
        }
        else if (n == 0)
        {
            goto __close;
        }
        if (cli->_redirect_to_socket)
        {
            ret = SwooleG.main_reactor->write(SwooleG.main_reactor, cli->_redirect_to_socket, buf, n);
        }
        else if (cli->_redirect_to_session)
        {
            if (SwooleG.serv->send(SwooleG.serv, cli->_redirect_to_session, buf, n) < 0)
            {
                if (SwooleG.error >= SW_ERROR_SESSION_CLOSED_BY_SERVER || SwooleG.error >= SW_ERROR_SESSION_INVALID_ID)
                {
                    goto __close;
                }
            }
            else
            {
                return SW_OK;
            }
        }
        else
        {
            ret = swSocket_write_blocking(cli->_redirect_to_file, buf, n);
        }
        if (ret < 0)
        {
            goto __error;
        }
        return SW_OK;
    }

    if (cli->open_eof_check || cli->open_length_check)
    {
        swConnection *conn = cli->socket;
        swProtocol *protocol = &cli->protocol;

        if (cli->open_eof_check)
        {
            n = swProtocol_recv_check_eof(protocol, conn, cli->buffer);
        }
        else
        {
            n = swProtocol_recv_check_length(protocol, conn, cli->buffer);
        }

        if (n < 0)
        {
            return  cli->close(cli);
        }
        else
        {
            return SW_OK;
        }
    }

#ifdef SW_CLIENT_RECV_AGAIN
    recv_again:
#endif
    n = swConnection_recv(event->socket, buf, buf_size, 0);
    if (n < 0)
    {
        __error:
        switch (swConnection_error(errno))
        {
        case SW_ERROR:
            swSysError("Read from socket[%d] failed.", event->fd);
            return SW_OK;
        case SW_CLOSE:
            goto __close;
        case SW_WAIT:
            return SW_OK;
        default:
            return SW_OK;
        }
    }
    else if (n == 0)
    {
        __close:
        return  cli->close(cli);
    }
    else
    {
        cli->onReceive(cli, buf, n);
#ifdef SW_CLIENT_RECV_AGAIN
        if (n == buf_size)
        {
            goto recv_again;
        }
#endif
        return SW_OK;
    }
    return SW_OK;
}
예제 #8
0
파일: socket.c 프로젝트: lzpfmh/swoole
int swSocket_listen(int type, char *host, int port, int backlog)
{
    int sock;
    int option;
    int ret;

    struct sockaddr_in addr_in4;
    struct sockaddr_in6 addr_in6;
    struct sockaddr_un addr_un;

    sock = swSocket_create(type);
    if (sock < 0)
    {
        swSysError("create socket failed.");
        return SW_ERR;
    }
    //reuse address
    option = 1;
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(int)) < 0)
    {
        swSysError("setsockopt(SO_REUSEPORT) failed.");
    }
    //reuse port
#ifdef HAVE_REUSEPORT
    if (SwooleG.reuse_port)
    {
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &option, sizeof(int)) < 0)
        {
            swSysError("setsockopt(SO_REUSEPORT) failed.");
            SwooleG.reuse_port = 0;
        }
    }
#endif
    //unix socket
    if (type == SW_SOCK_UNIX_DGRAM || type == SW_SOCK_UNIX_STREAM)
    {
        bzero(&addr_un, sizeof(addr_un));
        unlink(host);
        addr_un.sun_family = AF_UNIX;
        strcpy(addr_un.sun_path, host);
        ret = bind(sock, (struct sockaddr*) &addr_un, sizeof(addr_un));
    }
    //IPv6
    else if (type > SW_SOCK_UDP)
    {
        bzero(&addr_in6, sizeof(addr_in6));
        inet_pton(AF_INET6, host, &(addr_in6.sin6_addr));
        addr_in6.sin6_port = htons(port);
        addr_in6.sin6_family = AF_INET6;
        ret = bind(sock, (struct sockaddr *) &addr_in6, sizeof(addr_in6));
    }
    //IPv4
    else
    {
        bzero(&addr_in4, sizeof(addr_in4));
        inet_pton(AF_INET, host, &(addr_in4.sin_addr));
        addr_in4.sin_port = htons(port);
        addr_in4.sin_family = AF_INET;
        ret = bind(sock, (struct sockaddr *) &addr_in4, sizeof(addr_in4));
    }
    //bind failed
    if (ret < 0)
    {
        swWarn("bind(%s:%d) failed. Error: %s [%d]", host, port, strerror(errno), errno);
        return SW_ERR;
    }
    if (type == SW_SOCK_UDP || type == SW_SOCK_UDP6 || type == SW_SOCK_UNIX_DGRAM)
    {
        return sock;
    }
    //listen stream socket
    ret = listen(sock, backlog);
    if (ret < 0)
    {
        swWarn("listen(%s:%d, %d) failed. Error: %s[%d]", host, port, backlog, strerror(errno), errno);
        return SW_ERR;
    }
    swSetNonBlock(sock);
    return sock;
}
예제 #9
0
파일: Port.c 프로젝트: Baojs/swoole-src
int swPort_set_option(swListenPort *ls)
{
    int sock = ls->sock;

    //reuse address
    int option = 1;
    //reuse port
#ifdef HAVE_REUSEPORT
    if (SwooleG.reuse_port)
    {
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &option, sizeof(int)) < 0)
        {
            swSysError("setsockopt(SO_REUSEPORT) failed.");
            SwooleG.reuse_port = 0;
        }
    }
#endif

    if (swSocket_is_dgram(ls->type))
    {
        int bufsize = SwooleG.socket_buffer_size;
        setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
        setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
        return SW_OK;
    }

#ifdef SW_USE_OPENSSL
    if (ls->open_ssl_encrypt)
    {
        if (ls->ssl_cert_file == NULL || ls->ssl_key_file == NULL)
        {
            swWarn("SSL error, require ssl_cert_file and ssl_key_file.");
            return SW_ERR;
        }
        ls->ssl_context = swSSL_get_context(ls->ssl_method, ls->ssl_cert_file, ls->ssl_key_file);
        if (ls->ssl_context == NULL)
        {
            swWarn("swSSL_get_context() error.");
            return SW_ERR;
        }
        if (ls->ssl_client_cert_file && swSSL_set_client_certificate(ls->ssl_context, ls->ssl_client_cert_file, ls->ssl_verify_depth) == SW_ERR)
        {
            swWarn("swSSL_set_client_certificate() error.");
            return SW_ERR;
        }
        if (ls->open_http_protocol)
        {
            ls->ssl_config.http = 1;
        }
        if (ls->open_http2_protocol)
        {
            ls->ssl_config.http_v2 = 1;
            swSSL_server_http_advise(ls->ssl_context, &ls->ssl_config);
        }
        if (swSSL_server_set_cipher(ls->ssl_context, &ls->ssl_config) < 0)
        {
            swWarn("swSSL_server_set_cipher() error.");
            return SW_ERR;
        }
    }

    if (ls->ssl)
    {
        if (!ls->ssl_cert_file)
        {
            swWarn("need to set [ssl_cert_file] option.");
            return SW_ERR;
        }
        if (!ls->ssl_key_file)
        {
            swWarn("need to set [ssl_key_file] option.");
            return SW_ERR;
        }
    }
#endif

    //listen stream socket
    if (listen(sock, ls->backlog) < 0)
    {
        swWarn("listen(%s:%d, %d) failed. Error: %s[%d]", ls->host, ls->port, ls->backlog, strerror(errno), errno);
        return SW_ERR;
    }

#ifdef TCP_DEFER_ACCEPT
    if (ls->tcp_defer_accept)
    {
        if (setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, (const void*) &ls->tcp_defer_accept, sizeof(int)) < 0)
        {
            swSysError("setsockopt(TCP_DEFER_ACCEPT) failed.");
        }
    }
#endif

#ifdef TCP_FASTOPEN
    if (ls->tcp_fastopen)
    {
        if (setsockopt(sock, IPPROTO_TCP, TCP_FASTOPEN, (const void*) &ls->tcp_fastopen, sizeof(int)) < 0)
        {
            swSysError("setsockopt(TCP_FASTOPEN) failed.");
        }
    }
#endif

#ifdef SO_KEEPALIVE
    if (ls->open_tcp_keepalive == 1)
    {
        option = 1;
        if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &option, sizeof(option)) < 0)
        {
            swSysError("setsockopt(SO_KEEPALIVE) failed.");
        }
#ifdef TCP_KEEPIDLE
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, (void*) &ls->tcp_keepidle, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, (void *) &ls->tcp_keepinterval, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, (void *) &ls->tcp_keepcount, sizeof(int));
#endif
    }
#endif
    return SW_OK;
}
예제 #10
0
파일: Port.c 프로젝트: akrick/swoole-src
/**
 * For Http Protocol
 */
static int swPort_onRead_http(swReactor *reactor, swListenPort *port, swEvent *event)
{
    swConnection *conn = event->socket;

    if (conn->websocket_status >= WEBSOCKET_STATUS_HANDSHAKE)
    {
        if (conn->http_upgrade == 0)
        {
            swHttpRequest_free(conn);
            conn->websocket_status = WEBSOCKET_STATUS_ACTIVE;
            conn->http_upgrade = 1;
        }
        return swPort_onRead_check_length(reactor, port, event);
    }

#ifdef SW_USE_HTTP2
    if (conn->http2_stream)
    {
        return swPort_onRead_check_length(reactor, port, event);
    }
#endif

    int n = 0;
    char *buf;
    int buf_len;

    swHttpRequest *request = NULL;
    swProtocol *protocol = &port->protocol;

    //new http request
    if (conn->object == NULL)
    {
        request = sw_malloc(sizeof(swHttpRequest));
        bzero(request, sizeof(swHttpRequest));
        conn->object = request;
    }
    else
    {
        request = (swHttpRequest *) conn->object;
    }

    if (!request->buffer)
    {
        request->buffer = swString_new(SW_HTTP_HEADER_MAX_SIZE);
        //alloc memory failed.
        if (!request->buffer)
        {
            swReactorThread_onClose(reactor, event);
            return SW_ERR;
        }
    }

    swString *buffer = request->buffer;

    recv_data:
    buf = buffer->str + buffer->length;
    buf_len = buffer->size - buffer->length;

    n = swConnection_recv(conn, buf, buf_len, 0);
    if (n < 0)
    {
        switch (swConnection_error(errno))
        {
        case SW_ERROR:
            swSysError("recv from connection#%d failed.", event->fd);
            return SW_OK;
        case SW_CLOSE:
            conn->close_errno = errno;
            goto close_fd;
        default:
            return SW_OK;
        }
    }
    else if (n == 0)
    {
        close_fd:
        swHttpRequest_free(conn);
        swReactorThread_onClose(reactor, event);
        return SW_OK;
    }
    else
    {
        buffer->length += n;

        if (request->method == 0 && swHttpRequest_get_protocol(request) < 0)
        {
            if (request->buffer->length < SW_HTTP_HEADER_MAX_SIZE)
            {
                return SW_OK;
            }

            swWarn("get protocol failed.");
#ifdef SW_HTTP_BAD_REQUEST
            if (swConnection_send(conn, SW_STRL(SW_HTTP_BAD_REQUEST) - 1, 0) < 0)
            {
                swSysError("send() failed.");
            }
#endif
            goto close_fd;
        }

        if (request->method > HTTP_PRI)
        {
            swWarn("method no support");
            goto close_fd;
        }
#ifdef SW_USE_HTTP2
        else if (request->method == HTTP_PRI)
        {
            conn->http2_stream = 1;
            swHttp2_send_setting_frame(protocol, conn);
            if (n == sizeof(SW_HTTP2_PRI_STRING) - 1)
            {
                swHttpRequest_free(conn);
                return SW_OK;
            }
            swHttp2_parse_frame(protocol, conn, buf + (sizeof(SW_HTTP2_PRI_STRING) - 1), n - (sizeof(SW_HTTP2_PRI_STRING) - 1));
            swHttpRequest_free(conn);
            return SW_OK;
        }
#endif

        if (request->content_length == 0)
        {
            if (swHttpRequest_get_content_length(request) < 0)
            {
                if (memcmp(buffer->str + buffer->length - 4, "\r\n\r\n", 4) == 0)
                {
                    swReactorThread_dispatch(conn, buffer->str, buffer->length);
                    swHttpRequest_free(conn);
                    return SW_OK;
                }
                else if (buffer->size == buffer->length)
                {
                    swWarn("[0]http header is too long.");
                    goto close_fd;
                }
                //wait more data
                else
                {
                    goto recv_data;
                }
            }
            else if (request->content_length > (protocol->package_max_length - SW_HTTP_HEADER_MAX_SIZE))
            {
                swWarn("Content-Length is too big, MaxSize=[%d].", protocol->package_max_length - SW_HTTP_HEADER_MAX_SIZE);
                goto close_fd;
            }
        }

        //http header is not the end
        if (request->header_length == 0)
        {
            if (swHttpRequest_get_header_length(request) < 0)
            {
                if (buffer->size == buffer->length)
                {
                    swWarn("[2]http header is too long.");
                    goto close_fd;
                }
                else
                {
                    goto recv_data;
                }
            }
        }

        //total length
        uint32_t request_size = request->content_length + request->header_length;
        if (request_size > buffer->size && swString_extend(buffer, request_size) < 0)
        {
            goto close_fd;
        }

        //discard the redundant data
        if (buffer->length > request_size)
        {
            buffer->length = request_size;
        }

        if (buffer->length == request_size)
        {
            swReactorThread_dispatch(conn, buffer->str, buffer->length);
            swHttpRequest_free(conn);
        }
        else
        {
#ifdef SW_HTTP_100_CONTINUE
            //Expect: 100-continue
            if (swHttpRequest_has_expect_header(request))
            {
                swSendData _send;
                _send.data = "HTTP/1.1 100 Continue\r\n\r\n";
                _send.length = strlen(_send.data);

                int send_times = 0;
                direct_send:
                n = swConnection_send(conn, _send.data, _send.length, 0);
                if (n < _send.length)
                {
                    _send.data += n;
                    _send.length -= n;
                    send_times++;
                    if (send_times < 10)
                    {
                        goto direct_send;
                    }
                    else
                    {
                        swWarn("send http header failed");
                    }
                }
            }
            else
            {
                swTrace("PostWait: request->content_length=%d, buffer->length=%zd, request->header_length=%d\n",
                        request->content_length, buffer->length, request->header_length);
            }
#endif
            goto recv_data;
        }
    }
    return SW_OK;
}
예제 #11
0
static int swReactorKqueue_wait(swReactor *reactor, struct timeval *timeo)
{
    swEvent event;
    swFd fd_;
    swReactorKqueue *object = reactor->object;
    swReactor_handle handle;

    int i, n, ret;
    struct timespec t;
    struct timespec *t_ptr;
    bzero(&t, sizeof(t));

    if (reactor->timeout_msec == 0)
    {
        if (timeo == NULL)
        {
            reactor->timeout_msec = -1;
        }
        else
        {
            reactor->timeout_msec = timeo->tv_sec * 1000 + timeo->tv_usec / 1000;
        }
    }

    reactor->start = 1;

    while (reactor->running > 0)
    {
        if (reactor->onBegin != NULL)
        {
            reactor->onBegin(reactor);
        }
        if (reactor->timeout_msec > 0)
        {
            t.tv_sec = reactor->timeout_msec / 1000;
            t.tv_nsec = (reactor->timeout_msec - t.tv_sec * 1000) * 1000;
            t_ptr = &t;
        }
        else
        {
            t_ptr = NULL;
        }

        n = kevent(object->epfd, NULL, 0, object->events, object->event_max, t_ptr);
        if (n < 0)
        {
            swTrace("kqueue error.EP=%d | Errno=%d\n", object->epfd, errno);
            if (swReactor_error(reactor) < 0)
            {
                swWarn("Kqueue[#%d] Error: %s[%d]", reactor->id, strerror(errno), errno);
                return SW_ERR;
            }
            else
            {
                continue;
            }
        }
        else if (n == 0)
        {
            if (reactor->onTimeout != NULL)
            {
                reactor->onTimeout(reactor);
            }
            continue;
        }

        for (i = 0; i < n; i++)
        {
            swTraceLog(SW_TRACE_EVENT, "n %d events.", n);
            if (object->events[i].udata)
            {
                memcpy(&fd_, &(object->events[i].udata), sizeof(fd_));
                event.fd = fd_.fd;
                event.from_id = reactor->id;
                event.type = fd_.fdtype;
                event.socket = swReactor_get(reactor, event.fd);

                //read
                if (object->events[i].filter == EVFILT_READ)
                {
                    if (event.socket->removed)
                    {
                        continue;
                    }
                    handle = swReactor_getHandle(reactor, SW_EVENT_READ, event.type);
                    ret = handle(reactor, &event);
                    if (ret < 0)
                    {
                        swSysError("kqueue event read socket#%d handler failed.", event.fd);
                    }
                }
                //write
                else if (object->events[i].filter == EVFILT_WRITE)
                {
                    if (event.socket->removed)
                    {
                        continue;
                    }
                    handle = swReactor_getHandle(reactor, SW_EVENT_WRITE, event.type);
                    ret = handle(reactor, &event);
                    if (ret < 0)
                    {
                        swSysError("kqueue event write socket#%d handler failed.", event.fd);
                    }
                }
                else
                {
                    swWarn("unknown event filter[%d].", object->events[i].filter);
                }
            }
        }

        if (reactor->onFinish != NULL)
        {
            reactor->onFinish(reactor);
        }
        if (reactor->once)
        {
            break;
        }
    }
    return 0;
}
예제 #12
0
static int swReactorKqueue_set(swReactor *reactor, int fd, int fdtype)
{
    swReactorKqueue *this = reactor->object;
    struct kevent e;
    swFd fd_;
    int ret;
    bzero(&e, sizeof(e));

    int fflags = 0;
    fd_.fd = fd;
    fd_.fdtype = swReactor_fdtype(fdtype);

    if (swReactor_event_read(fdtype))
    {
#ifdef NOTE_EOF
        fflags = NOTE_EOF;
#endif
        EV_SET(&e, fd, EVFILT_READ, EV_ADD, fflags, 0, NULL);
        memcpy(&e.udata, &fd_, sizeof(swFd));
        ret = kevent(this->epfd, &e, 1, NULL, 0, NULL);
        if (ret < 0)
        {
            swSysError("kqueue->set(%d, SW_EVENT_READ) failed.", fd);
            return SW_ERR;
        }
    }
    else
    {
        EV_SET(&e, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
        memcpy(&e.udata, &fd_, sizeof(swFd));
        ret = kevent(this->epfd, &e, 1, NULL, 0, NULL);
        if (ret < 0)
        {
            swSysError("kqueue->del(%d, SW_EVENT_READ) failed.", fd);
            return SW_ERR;
        }
    }

    if (swReactor_event_write(fdtype))
    {
        EV_SET(&e, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
        memcpy(&e.udata, &fd_, sizeof(swFd));
        ret = kevent(this->epfd, &e, 1, NULL, 0, NULL);
        if (ret < 0)
        {
            swSysError("kqueue->set(%d, SW_EVENT_WRITE) failed.", fd);
            return SW_ERR;
        }
    }
    else
    {
        EV_SET(&e, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
        memcpy(&e.udata, &fd_, sizeof(swFd));
        ret = kevent(this->epfd, &e, 1, NULL, 0, NULL);
        if (ret < 0)
        {
            swSysError("kqueue->del(%d, SW_EVENT_WRITE) failed.", fd);
            return SW_ERR;
        }
    }
    swTraceLog(SW_TRACE_EVENT, "[THREAD #%d]EP=%d|FD=%d, events=%d", SwooleTG.id, this->epfd, fd, fdtype);
    //execute parent method
    swReactor_set(reactor, fd, fdtype);
    return SW_OK;
}
예제 #13
0
/**
 * Use message queue ipc
 */
int swFactoryProcess_writer_loop_queue(swThreadParam *param)
{
    swEventData *resp;
    swServer *serv = SwooleG.serv;

    int pti = param->pti;
    swQueue_data sdata;
    //必须加1,msg_type必须不能为0
    sdata.mtype = pti + 1;

    swSignal_none();
    while (SwooleG.running > 0)
    {
        swTrace("[Writer]wt_queue[%ld]->out wait", sdata.mtype);
        if (serv->write_queue.out(&serv->write_queue, &sdata, sizeof(sdata.mdata)) < 0)
        {
            if (errno == EINTR)
            {
                continue;
            }
            swSysError("[writer#%d]wt_queue->out() failed.", pti);
        }
        else
        {
            int ret;
            resp = (swEventData *) sdata.mdata;

            //close connection
            //TODO: thread safe, should close in reactor thread.
            if (resp->info.type == SW_EVENT_CLOSE)
            {
                close_fd:
                swServer_connection_close(SwooleG.serv, resp->info.fd);
                continue;
            }
            //sendfile
            else if (resp->info.type == SW_EVENT_SENDFILE)
            {
                ret = swSocket_sendfile_sync(resp->info.fd, resp->data, SW_WRITER_TIMEOUT);
            }
            //send data
            else
            {
                ret = swConnection_send_blocking(resp->info.fd, resp->data, resp->info.len, 1000 * SW_WRITER_TIMEOUT);
            }

            if (ret < 0)
            {
                switch (swConnection_error(errno))
                {
                case SW_ERROR:
                    swSysError("send to client[%d] failed.", resp->info.fd);
                    break;
                case SW_CLOSE:
                    goto close_fd;
                default:
                    break;
                }
            }
        }
    }
    pthread_exit((void *) param);
    return SW_OK;
}
예제 #14
0
static int swFactoryProcess_manager_loop(swFactory *factory)
{
    int pid, new_pid;
    int i;
    int reload_worker_i = 0;
    int reload_worker_num;
    int ret;
    int worker_exit_code;

    SwooleG.use_signalfd = 0;
    SwooleG.use_timerfd = 0;

    memset(&ManagerProcess, 0, sizeof(ManagerProcess));

    swServer *serv = factory->ptr;
    swWorker *reload_workers;

    if (serv->onManagerStart)
    {
        serv->onManagerStart(serv);
    }

    reload_worker_num = serv->worker_num + SwooleG.task_worker_num;
    reload_workers = sw_calloc(reload_worker_num, sizeof(swWorker));
    if (reload_workers == NULL)
    {
        swError("malloc[reload_workers] failed");
        return SW_ERR;
    }

    //for reload
    swSignal_add(SIGTERM, swManager_signal_handle);
    swSignal_add(SIGUSR1, swManager_signal_handle);
    swSignal_add(SIGUSR2, swManager_signal_handle);
    //swSignal_add(SIGINT, swManager_signal_handle);

    while (SwooleG.running > 0)
    {
        pid = wait(&worker_exit_code);

        if (pid < 0)
        {
            if (ManagerProcess.reloading == 0)
            {
                swTrace("wait() failed. Error: %s [%d]", strerror(errno), errno);
            }
            else if (ManagerProcess.reload_event_worker == 1)
            {
                memcpy(reload_workers, serv->workers, sizeof(swWorker) * serv->worker_num);
                reload_worker_num = serv->worker_num;
                if (SwooleG.task_worker_num > 0)
                {
                    memcpy(reload_workers + serv->worker_num, SwooleG.task_workers.workers,
                            sizeof(swWorker) * SwooleG.task_worker_num);
                    reload_worker_num += SwooleG.task_worker_num;
                }
                reload_worker_i = 0;
                ManagerProcess.reload_event_worker = 0;
                goto kill_worker;
            }
            else if (ManagerProcess.reload_task_worker == 1)
            {
                if (SwooleG.task_worker_num == 0)
                {
                    swWarn("Cannot reload workers, because server no have task workers.");
                    continue;
                }
                memcpy(reload_workers, SwooleG.task_workers.workers, sizeof(swWorker) * SwooleG.task_worker_num);
                reload_worker_num = SwooleG.task_worker_num;
                reload_worker_i = 0;
                ManagerProcess.reload_task_worker = 0;
                goto kill_worker;
            }
        }
        if (SwooleG.running == 1)
        {
            for (i = 0; i < serv->worker_num; i++)
            {
                //compare PID
                if (pid != serv->workers[i].pid)
                {
                    continue;
                }
                else
                {
                    if (serv->onWorkerError != NULL && WEXITSTATUS(worker_exit_code) > 0)
                    {
                        serv->onWorkerError(serv, i, pid, WEXITSTATUS(worker_exit_code));
                    }
                    pid = 0;
                    while (1)
                    {
                        new_pid = swFactoryProcess_worker_spawn(factory, i);
                        if (new_pid < 0)
                        {
                            usleep(100000);
                            continue;
                        }
                        else
                        {
                            serv->workers[i].pid = new_pid;
                            break;
                        }
                    }
                }
            }

            //task worker
            if (pid > 0)
            {
                swWorker *exit_worker = swHashMap_find_int(SwooleG.task_workers.map, pid);
                if (exit_worker != NULL)
                {
                    swProcessPool_spawn(exit_worker);
                }
            }
        }
        //reload worker
        kill_worker:
        if (ManagerProcess.reloading == 1)
        {
            //reload finish
            if (reload_worker_i >= reload_worker_num)
            {
                ManagerProcess.reloading = 0;
                reload_worker_i = 0;
                continue;
            }
            ret = kill(reload_workers[reload_worker_i].pid, SIGTERM);
            if (ret < 0)
            {
                swSysError("[Manager]kill(%d) failed.", reload_workers[reload_worker_i].pid);
                continue;
            }
            reload_worker_i++;
        }
    }

    sw_free(reload_workers);

    //kill all child process
    for (i = 0; i < serv->worker_num; i++)
    {
        swTrace("[Manager]kill worker processor");
        kill(serv->workers[i].pid, SIGTERM);
    }

    if (SwooleG.task_worker_num > 0)
    {
        swProcessPool_shutdown(&SwooleG.task_workers);
    }

    if (serv->onManagerStop)
    {
        serv->onManagerStop(serv);
    }
    return SW_OK;
}
예제 #15
0
파일: Worker.c 프로젝트: akrick/swoole-src
void swWorker_signal_handler(int signo)
{
    switch (signo)
    {
    case SIGTERM:
        if (SwooleG.main_reactor)
        {
            SwooleG.main_reactor->running = 0;
        }
        else
        {
            SwooleG.running = 0;
        }
        break;
    case SIGALRM:
        swSystemTimer_signal_handler(SIGALRM);
        break;
    /**
     * for test
     */
    case SIGVTALRM:
        swWarn("SIGVTALRM coming");
        break;
    case SIGUSR1:
        if (SwooleG.main_reactor)
        {
            swWorker *worker = SwooleWG.worker;
            swWarn(" the worker %d get the signo", worker->pid);
            SwooleWG.reload = 1;
            SwooleWG.reload_count = 0;

            //删掉read管道
            swConnection *socket = swReactor_get(SwooleG.main_reactor, worker->pipe_worker);
            if (socket->events & SW_EVENT_WRITE)
            {
                socket->events &= (~SW_EVENT_READ);
                if (SwooleG.main_reactor->set(SwooleG.main_reactor, worker->pipe_worker, socket->fdtype | socket->events) < 0)
                {
                    swSysError("reactor->set(%d, SW_EVENT_READ) failed.", worker->pipe_worker);
                }
            }
            else
            {
                if (SwooleG.main_reactor->del(SwooleG.main_reactor, worker->pipe_worker) < 0)
                {
                    swSysError("reactor->del(%d) failed.", worker->pipe_worker);
                }
            }
        }
        else
        {
            SwooleG.running = 0;
        }
        break;

    case SIGUSR2:
        break;
    default:
#ifdef SIGRTMIN
        if (signo == SIGRTMIN)
        {
            swServer_reopen_log_file(SwooleG.serv);
        }
#endif
        break;
    }
}