static PHP_METHOD(swoole_process, __construct)
{
	zend_bool redirect_stdin_and_stdout = 0;
	zend_bool create_pipe = 1;
	zval *callback;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|bb", &callback, &redirect_stdin_and_stdout, &create_pipe) == FAILURE)
    {
        RETURN_FALSE;
    }

    char *func_name = NULL;
    if (!zend_is_callable(callback, 0, &func_name TSRMLS_CC))
    {
        php_error_docref(NULL TSRMLS_CC, E_ERROR, "function '%s' is not callable", func_name);
        efree(func_name);
        RETURN_FALSE;
    }
    efree(func_name);

	swWorker *process = emalloc(sizeof(swWorker));
	bzero(process, sizeof(swWorker));

    process->id = php_swoole_worker_round_id++;

    if (php_swoole_worker_round_id == 0)
    {
        php_swoole_worker_round_id = 1;
    }

    if (redirect_stdin_and_stdout)
    {
        process->redirect_stdin = 1;
        process->redirect_stdout = 1;
        create_pipe = 1;
    }

    if (create_pipe)
    {
        swPipe *_pipe = emalloc(sizeof(swWorker));
        if (swPipeUnsock_create(_pipe, 1, SOCK_STREAM) < 0)
        {
            RETURN_FALSE;
        }
        process->pipe_object = _pipe;
        process->pipe_master = _pipe->getFd(_pipe, SW_PIPE_MASTER);
        process->pipe_worker = _pipe->getFd(_pipe, SW_PIPE_WORKER);
        process->pipe = process->pipe_master;

        zend_update_property_long(swoole_process_class_entry_ptr, getThis(), ZEND_STRL("pipe"), process->pipe_master TSRMLS_CC);
    }

    swoole_set_object(getThis(), process);
	zend_update_property(swoole_process_class_entry_ptr, getThis(), ZEND_STRL("callback"), callback TSRMLS_CC);
}
Exemple #2
0
/**
 * Process manager
 */
int swProcessPool_create(swProcessPool *pool, int worker_num, int max_request, key_t msgqueue_key)
{
	bzero(pool, sizeof(swProcessPool));
	pool->workers = sw_calloc(worker_num, sizeof(swWorker));
	pool->worker_num = worker_num;
	pool->max_request = max_request;

	if (pool->workers == NULL)
	{
		swWarn("malloc[1] failed.");
		return SW_ERR;
	}
	pool->pipes = sw_calloc(worker_num, sizeof(swPipe));
	if (pool->pipes == NULL)
	{
		swWarn("malloc[2] failed.");
		sw_free(pool->workers);
		return SW_ERR;
	}

	int i;
	if (msgqueue_key > 0)
	{
		if (swQueueMsg_create(&pool->queue, 1, msgqueue_key, 1) < 0)
		{
			return SW_ERR;
		}
		pool->use_msgqueue = 1;
		pool->msgqueue_key = msgqueue_key;
	}
	else
	{
		swPipe *pipe;
		for (i = 0; i < worker_num; i++)
		{
			pipe = &pool->pipes[i];
			if (swPipeUnsock_create(pipe, 1, SOCK_DGRAM) < 0)
			{
				return SW_ERR;
			}
			swProcessPool_worker(pool, i).pipe_master = pipe->getFd(pipe, 1);
			swProcessPool_worker(pool, i).pipe_worker = pipe->getFd(pipe, 0);
		}
	}

	for (i = 0; i < worker_num; i++)
	{
		swProcessPool_worker(pool, i).id = i;
		swProcessPool_worker(pool, i).pool = pool;
	}
	pool->main_loop = swProcessPool_worker_start;
	return SW_OK;
}
Exemple #3
0
int swProcessPool_add_worker(swProcessPool *ma, swWorkerCall cb)
{
	swPipe pipe;
	if (ma->worker_num >= ma->max_num)
	{
		swWarn("[swProcessPool_create] too many worker[max_num=%d]", ma->max_num);
		return SW_ERR;
	}
	int cur_id = ma->worker_num++;

	swProcessPool_worker(ma, cur_id).call = cb;
	if (swPipeUnsock_create(&pipe, 1, SOCK_STREAM) < 0)
	{
		return SW_ERR;
	}
	swProcessPool_worker(ma, cur_id).pipe_master = pipe.getFd(&pipe, 1);
	swProcessPool_worker(ma, cur_id).pipe_worker = pipe.getFd(&pipe, 0);
	swProcessPool_worker(ma, cur_id).id = cur_id;
	return cur_id;
}
Exemple #4
0
/**
 * Process manager
 */
int swProcessPool_create(swProcessPool *pool, int worker_num, int max_request, key_t msgqueue_key, int ipc_mode)
{
    bzero(pool, sizeof(swProcessPool));

    pool->worker_num = worker_num;
    pool->max_request = max_request;

    pool->workers = SwooleG.memory_pool->alloc(SwooleG.memory_pool, worker_num * sizeof(swWorker));
    if (pool->workers == NULL)
    {
        swSysError("malloc[1] failed.");
        return SW_ERR;
    }

    if (ipc_mode == SW_IPC_MSGQUEUE)
    {
        pool->use_msgqueue = 1;
        pool->msgqueue_key = msgqueue_key;

        pool->queue = sw_malloc(sizeof(swMsgQueue));
        if (pool->queue == NULL)
        {
            swSysError("malloc[2] failed.");
            return SW_ERR;
        }

        if (swMsgQueue_create(pool->queue, 1, pool->msgqueue_key, 1) < 0)
        {
            return SW_ERR;
        }
    }
    else if (ipc_mode == SW_IPC_SOCKET)
    {
        pool->use_socket = 1;
        pool->stream = sw_malloc(sizeof(swStreamInfo));
        if (pool->stream == NULL)
        {
            swWarn("malloc[2] failed.");
            return SW_ERR;
        }
        pool->stream->last_connection = 0;
    }
    else if (ipc_mode == SW_IPC_UNIXSOCK)
    {
        pool->pipes = sw_calloc(worker_num, sizeof(swPipe));
        if (pool->pipes == NULL)
        {
            swWarn("malloc[2] failed.");
            return SW_ERR;
        }

        swPipe *pipe;
        int i;
        for (i = 0; i < worker_num; i++)
        {
            pipe = &pool->pipes[i];
            if (swPipeUnsock_create(pipe, 1, SOCK_DGRAM) < 0)
            {
                return SW_ERR;
            }
            pool->workers[i].pipe_master = pipe->getFd(pipe, SW_PIPE_MASTER);
            pool->workers[i].pipe_worker = pipe->getFd(pipe, SW_PIPE_WORKER);
            pool->workers[i].pipe_object = pipe;
        }
    }
    else
    {
        swWarn("unknown ipc_type [%d].", ipc_mode);
        return SW_ERR;
    }

    pool->map = swHashMap_new(SW_HASHMAP_INIT_BUCKET_N, NULL);
    if (pool->map == NULL)
    {
        swProcessPool_free(pool);
        return SW_ERR;
    }

    pool->ipc_mode = ipc_mode;
    pool->main_loop = swProcessPool_worker_loop;

    return SW_OK;
}
Exemple #5
0
//create worker child proccess
static int swFactoryProcess_manager_start(swFactory *factory)
{
	swFactoryProcess *object = factory->object;
	int i, pid, ret;
	int writer_pti;

	swServer *serv = factory->ptr;

#if SW_WORKER_IPC_MODE == 2
#define _SW_PATH_BUF_LEN   128
	//这里使用ftok来获取消息队列的key
	char path_buf[_SW_PATH_BUF_LEN];
	char *path_ptr = getcwd(path_buf, _SW_PATH_BUF_LEN);
	//读数据队列
	if(swQueueMsg_create(&object->rd_queue, 1, ftok(path_ptr, 1), 1) < 0)
	{
		swError("[Master] swPipeMsg_create[In] fail. Error: %s [%d]", strerror(errno), errno);
		return SW_ERR;
	}
	//为TCP创建写队列
	if (serv->have_tcp_sock == 1)
	{
		//写数据队列
		if(swQueueMsg_create(&object->wt_queue, 1, ftok(path_ptr, 2), 1) < 0)
		{
			swError("[Master] swPipeMsg_create[out] fail. Error: %s [%d]", strerror(errno), errno);
			return SW_ERR;
		}
	}
#else
	object->pipes = sw_calloc(object->worker_num, sizeof(swPipe));
	if (object->pipes == NULL)
	{
		swError("malloc[worker_pipes] fail. Error: %s [%d]", strerror(errno), errno);
		return SW_ERR;
	}
	//worker进程的pipes
	for (i = 0; i < object->worker_num; i++)
	{
		if (swPipeUnsock_create(&object->pipes[i], 1, SOCK_DGRAM) < 0)
		{
			swError("create unix socket[1] fail");
			return SW_ERR;
		}
		object->workers[i].pipe_master = object->pipes[i].getFd(&object->pipes[i], 1);
		object->workers[i].pipe_worker = object->pipes[i].getFd(&object->pipes[i], 0);
	}
#endif
	if (serv->task_worker_num > 0)
	{
		if (swProcessPool_create(&SwooleG.task_workers, serv->task_worker_num, serv->max_request)< 0)
		{
			swWarn("[Master] create task_workers fail");
			return SW_ERR;
		}
		//设置指针和回调函数
		SwooleG.task_workers.ptr = serv;
		SwooleG.task_workers.onTask = swTaskWorker_onTask;
	}
	pid = fork();
	switch (pid)
	{
	//创建manager进程
	case 0:
		for (i = 0; i < object->worker_num; i++)
		{
//			close(worker_pipes[i].pipes[0]);
			writer_pti = (i % object->writer_num);
			object->workers[i].writer_id = writer_pti;
			pid = swFactoryProcess_worker_spawn(factory, i);
			if (pid < 0)
			{
				swError("Fork worker process fail");
				return SW_ERR;
			}
			else
			{
				object->workers[i].pid = pid;
			}
		}
		//创建task_worker进程
		if (serv->task_worker_num > 0)
		{
			swProcessPool_start(&SwooleG.task_workers);
		}
		//标识为管理进程
		SwooleG.process_type = SW_PROCESS_MANAGER;
		ret = swFactoryProcess_manager_loop(factory);
		exit(ret);
		break;
		//主进程
	default:
		object->manager_pid = pid;
		//TCP需要writer线程
		if (serv->have_tcp_sock == 1)
		{
			int ret = swFactoryProcess_writer_start(factory);
			if (ret < 0)
			{
				return SW_ERR;
			}
		}
#if SW_WORKER_IPC_MODE != 2
		for (i = 0; i < object->worker_num; i++)
		{
			writer_pti = (i % object->writer_num);
			object->workers[i].writer_id = writer_pti;

			if (serv->have_tcp_sock == 1)
			{
				//将写pipe设置到writer的reactor中
				object->writers[writer_pti].reactor.add(&(object->writers[writer_pti].reactor),
						object->workers[i].pipe_master, SW_FD_PIPE);
			}
		}
#endif
		break;
	case -1:
		swError("[swFactoryProcess_worker_start]fork manager process fail\n");
		return SW_ERR;
	}
	return SW_OK;
}
Exemple #6
0
/**
 * Process manager
 */
int swProcessPool_create(swProcessPool *pool, int worker_num, int max_request, key_t msgqueue_key, int create_pipe)
{
    bzero(pool, sizeof(swProcessPool));

    pool->worker_num = worker_num;
    pool->max_request = max_request;

    if (msgqueue_key > 0)
    {
        pool->use_msgqueue = 1;
        pool->msgqueue_key = msgqueue_key;
    }
    
    pool->workers = SwooleG.memory_pool->alloc(SwooleG.memory_pool, worker_num * sizeof(swWorker));
    if (pool->workers == NULL)
    {
        swSysError("malloc[1] failed.");
        return SW_ERR;
    }

    pool->map = swHashMap_new(SW_HASHMAP_INIT_BUCKET_N, NULL);
    if (pool->map == NULL)
    {
        return SW_ERR;
    }

    pool->queue = sw_malloc(sizeof(swQueue));
    if (pool->queue == NULL)
    {
        swSysError("malloc[2] failed.");
        return SW_ERR;
    }

    int i;
    if (pool->use_msgqueue)
    {
        if (swQueueMsg_create(pool->queue, 1, pool->msgqueue_key, 1) < 0)
        {
            return SW_ERR;
        }
    }
    else if (create_pipe)
    {
        pool->pipes = sw_calloc(worker_num, sizeof(swPipe));
        if (pool->pipes == NULL)
        {
            swWarn("malloc[2] failed.");
            sw_free(pool->workers);
            return SW_ERR;
        }

        swPipe *pipe;
        for (i = 0; i < worker_num; i++)
        {
            pipe = &pool->pipes[i];
            if (swPipeUnsock_create(pipe, 1, SOCK_DGRAM) < 0)
            {
                return SW_ERR;
            }
            pool->workers[i].pipe_master = pipe->getFd(pipe, SW_PIPE_MASTER);
            pool->workers[i].pipe_worker = pipe->getFd(pipe, SW_PIPE_WORKER);
            pool->workers[i].pipe_object = pipe;
        }
    }
    pool->main_loop = swProcessPool_worker_start;
    return SW_OK;
}
Exemple #7
0
//create worker child proccess
static int swFactoryProcess_manager_start(swFactory *factory)
{
	swFactoryProcess *object = factory->object;
	int i, pid, ret;
	int reactor_pti;
	swServer *serv = factory->ptr;

	if (serv->ipc_mode == SW_IPC_MSGQUEUE)
	{
		//读数据队列
		if (swQueueMsg_create(&object->rd_queue, 1, serv->message_queue_key, 1) < 0)
		{
			swError("[Master] swPipeMsg_create[In] fail. Error: %s [%d]", strerror(errno), errno);
			return SW_ERR;
		}
		//为TCP创建写队列
		if (serv->have_tcp_sock == 1)
		{
			//写数据队列
			if (swQueueMsg_create(&object->wt_queue, 1, serv->message_queue_key + 1, 1) < 0)
			{
				swError("[Master] swPipeMsg_create[out] fail. Error: %s [%d]", strerror(errno), errno);
				return SW_ERR;
			}
		}
	}
	else
	{
		object->pipes = sw_calloc(serv->worker_num, sizeof(swPipe));
		if (object->pipes == NULL)
		{
			swError("malloc[worker_pipes] fail. Error: %s [%d]", strerror(errno), errno);
			return SW_ERR;
		}
		//worker进程的pipes
		for (i = 0; i < serv->worker_num; i++)
		{
			if (swPipeUnsock_create(&object->pipes[i], 1, SOCK_DGRAM) < 0)
			{
				swError("create unix socket[1] fail");
				return SW_ERR;
			}
			object->workers[i].pipe_master = object->pipes[i].getFd(&object->pipes[i], 1);
			object->workers[i].pipe_worker = object->pipes[i].getFd(&object->pipes[i], 0);
		}
	}


	if (SwooleG.task_worker_num > 0)
	{
		key_t msgqueue_key = 0;
		if (SwooleG.task_ipc_mode > 0)
		{
			msgqueue_key =  serv->message_queue_key + 2;
		}
		if (swProcessPool_create(&SwooleG.task_workers, SwooleG.task_worker_num, serv->max_request, msgqueue_key)< 0)
		{
			swWarn("[Master] create task_workers fail");
			return SW_ERR;
		}
		//设置指针和回调函数
		SwooleG.task_workers.ptr = serv;
		SwooleG.task_workers.onTask = swTaskWorker_onTask;
		if (serv->onWorkerStart != NULL)
		{
			SwooleG.task_workers.onWorkerStart = swTaskWorker_onWorkerStart;
		}
	}
	pid = fork();
	switch (pid)
	{
	//创建manager进程
	case 0:
		//创建子进程
		for (i = 0; i < serv->worker_num; i++)
		{
			//close(worker_pipes[i].pipes[0]);
			reactor_pti = (i % serv->writer_num);
			object->workers[i].reactor_id = reactor_pti;
			pid = swFactoryProcess_worker_spawn(factory, i);
			if (pid < 0)
			{
				swError("Fork worker process fail");
				return SW_ERR;
			}
			else
			{
				object->workers[i].pid = pid;
			}
		}
		/**
		 * create task worker pool
		 */
		if (SwooleG.task_worker_num > 0)
		{
			swProcessPool_start(&SwooleG.task_workers);
		}
		//标识为管理进程
		SwooleG.process_type = SW_PROCESS_MANAGER;
		ret = swFactoryProcess_manager_loop(factory);
		exit(ret);
		break;
		//主进程
	default:
		SwooleGS->manager_pid = pid;
		break;
	case -1:
		swError("[swFactoryProcess_worker_start]fork manager process fail");
		return SW_ERR;
	}
	return SW_OK;
}
static PHP_METHOD(swoole_process, __construct)
{
    zend_bool redirect_stdin_and_stdout = 0;
    long pipe_type = 2;
    zval *callback;

    //only cli env
    if (!SWOOLE_G(cli))
    {
        swoole_php_fatal_error(E_ERROR, "swoole_process must run at php_cli environment.");
        RETURN_FALSE;
    }

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|bl", &callback, &redirect_stdin_and_stdout, &pipe_type) == FAILURE)
    {
        RETURN_FALSE;
    }

    char *func_name = NULL;
    if (!sw_zend_is_callable(callback, 0, &func_name TSRMLS_CC))
    {
        swoole_php_fatal_error(E_ERROR, "function '%s' is not callable", func_name);
        efree(func_name);
        RETURN_FALSE;
    }
    efree(func_name);

    swWorker *process = emalloc(sizeof(swWorker));
    bzero(process, sizeof(swWorker));

    process->id = php_swoole_worker_round_id++;

    if (php_swoole_worker_round_id == 0)
    {
        php_swoole_worker_round_id = 1;
    }

    if (redirect_stdin_and_stdout)
    {
        process->redirect_stdin = 1;
        process->redirect_stdout = 1;
        process->redirect_stderr = 1;
        pipe_type = 2;
    }

    if (pipe_type > 0)
    {
        swPipe *_pipe = emalloc(sizeof(swWorker));
        int socket_type = pipe_type == 1 ? SOCK_STREAM : SOCK_DGRAM;
        if (swPipeUnsock_create(_pipe, 1, socket_type) < 0)
        {
            RETURN_FALSE;
        }

        process->pipe_object = _pipe;
        process->pipe_master = _pipe->getFd(_pipe, SW_PIPE_MASTER);
        process->pipe_worker = _pipe->getFd(_pipe, SW_PIPE_WORKER);
        process->pipe = process->pipe_master;

        zend_update_property_long(swoole_process_class_entry_ptr, getThis(), ZEND_STRL("pipe"), process->pipe_master TSRMLS_CC);
    }

    swoole_set_object(getThis(), process);
    zend_update_property(swoole_process_class_entry_ptr, getThis(), ZEND_STRL("callback"), callback TSRMLS_CC);
}