diff --git a/README.md b/README.md
index 6080dc4adf8..88f20e7963b 100644
--- a/README.md
+++ b/README.md
@@ -1,40 +1,512 @@
-The PHP Interpreter
-===================
+# 项目说明[中文]
 
-This is the github mirror of the official PHP repository located at
-http://git.php.net.
+项目名称PHPCE,全名PHP-Coroutine-Engine
 
-[![Build Status](https://secure.travis-ci.org/php/php-src.svg?branch=master)](http://travis-ci.org/php/php-src)
-[![Build status](https://ci.appveyor.com/api/projects/status/meyur6fviaxgdwdy?svg=true)](https://ci.appveyor.com/project/php/php-src)
+本项目是php7的分支，主要功能是在php7的基础上实现协程。
 
-Pull Requests
-=============
-PHP accepts pull requests via github. Discussions are done on github, but
-depending on the topic can also be relayed to the official PHP developer
-mailing list internals@lists.php.net.
+这个项目是从php官方的github中fork出来的版本，基于php7.1.17版本。
 
-New features require an RFC and must be accepted by the developers.
-See https://wiki.php.net/rfc and https://wiki.php.net/rfc/voting for more
-information on the process.
+协程是一种可以支持高并发服务器的设计模式。
 
-Bug fixes **do not** require an RFC, but require a bugtracker ticket. Always
-open a ticket at https://bugs.php.net and reference the bug id using #NNNNNN.
+现在主流的服务器端语言和框架均支持协程调用，包括golang、openresty、java、swoole等。
 
-    Fix #55371: get_magic_quotes_gpc() throws deprecation warning
+协程可以降低服务器阻塞，对于需要使用远程调用的服务如使用rpc、mysql、redis等场景，使用协程可以显著提升服务器性能。
 
-    After removing magic quotes, the get_magic_quotes_gpc function caused
-    a deprecate warning. get_magic_quotes_gpc can be used to detected
-    the magic_quotes behavior and therefore should not raise a warning at any
-    time. The patch removes this warning
+协程本质是一种服务器端异步非阻塞IO模型的实现方式之一。
 
-We do not merge pull requests directly on github. All PRs will be
-pulled and pushed through http://git.php.net.
+传统php-fpm的设计模式主要是通过多进程来进行并发处理请求。对于服务器资源的使用不充分。
 
+本项目就是通过对php-fpm源码进行改造，实现了协程模式的php-fpm，最终可以像nginx一样，几个进程即可处理大量的并发请求，充分的利用CPU资源，成倍提升php服务器性能。
 
-Guidelines for contributors
-===========================
-- [CODING_STANDARDS](/CODING_STANDARDS)
-- [README.GIT-RULES](/README.GIT-RULES)
-- [README.MAILINGLIST_RULES](/README.MAILINGLIST_RULES)
-- [README.RELEASE_PROCESS](/README.RELEASE_PROCESS)
+提示：本项目未经过完整测试，请小心，不建议使用在生产环境。
+
+作者 email :sioomy@qq.com ,如有问题，请联系我。
+
+最后，这个项目完成过程挺不容易的，要感谢一下这个项目开发过程中给予支持的各位老大和同事，尤其是WorkerMan的作者worker,滴滴开源的大牛陈雷，swoole的核心开发者桶哥，以及我的直属领导宏杰的支持。接下来还要在实际应用中测试，以及开发更多支持协程的扩展。也希望更多的开发着加入进来，给予支持和指导。
+
+
+## 协程原理
+
+(注：看不到图的同学请更换DNS试试)
+
+![avatar](/tutorial/pic/coroutine.jpg)
+
+协程本质是异步非阻塞IO的实现方式之一。php-fpm要想实现协程，需要分成两部分，一部分是调度器，另外一部分就是在PHP扩展中实现协程逻辑。
+
+PHP-FPM就是充当着调度器的角色。
+
+当有请求进来之后，调度器会触发一次执行。在这次请求的执行过程中，如果遇到php代码中有远程调用，则会在请求发送之后，php自动将控制权交给调度器。调度器这个时候可以决定处理其他新进来请求，还是处理之前远程调用返回来的可以继续执行的请求。
+
+每个请求会从协程池中取出一个协程上下文进行绑定，请求结束后，则会将协程上下文放回去，以便其他请求复用。
+
+协程上下文主要存放的是php运行环境中用到的全局和私有变量。这块的实现主要是利用php的多线程安全存储(注意不是多线程)，既TSRM相关库。
+
+TSRM库会将所有php全局变量获取宏以及php内存池进行隔离。
+
+所以在开发协程扩展的时候，要注意全局变量获取宏如EG()、SG()、emalloc、efree等的使用。
+
+支持协程的php-fpm在编译过程中需要增加 --enable-maintainer-zts 参数告诉编译器，要求支持zts多线程安全存储。
+
+在多线程安全存储模式下，php使用的内部内存的存储方式大致可以理解为一个矩阵。矩阵的纵轴是每个线程（协程）。矩阵的横轴存储的是所有运行环境中需要用到的内存。也就是说每个php协程都有一套自己的内存。
+
+协程版本的php因为利用了多线程安全存储(TSRM)。所以此版本的php-fpm用到的扩展以及应用层的php代码是不支持多线程的。
+
+## 压测报告
+
+只做了简单压测，系统并没有做优化。以后会优化
+
+机器是2016款的MAC PRO，配置是2核，8G内存
+
+压测工具使用的是wrk,命令如下
+```
+./wrk -c 800 -t 800 -d 120s http://localhost/test.php
+```
+开启800个线程 800个连接压测，相当于800个并发请求。
+
+理论上每个请求2秒返回，极限的压测效果是400qps
+
+请求流程是:
+```
+wrk >> nginx >> php-fpm >> nodejs
+```
+wrk客户端访问NGINX FASTCGI反向代理，nginx访问php-fpm, php-fpm通过协程函数访问NODEJS程序
+
+nodejs程序在8080端口，模拟2秒钟返回结果的接口。
+
+test.js程序位置: tutorial/test.js
+
+nodejs 启动命令:
+```
+ node tutorial/test.js
+```
+test.php位置:   tutorial/test.php
+
+test.php 通过coro_http_get(实现协程的http客户端)调用test.js
+```
+ var_dump(coro_http_get("http://localhost:8080/"));
+```
+这个测试中，php-fpm 启动了8个进程，PHP-FPM中每进程设置的最大内存使用大小为128M
+
+NGINX启动了8个进程
+
+压测结果如下：
+
+![avatar](/tutorial/pic/rt.png)
+
+系统占用情况抓图1：
+
+![avatar](/tutorial/pic/top1.png)
+
+系统占用情况抓图2：
+
+![avatar](/tutorial/pic/top2.png)
+
+在压测过程中，通过curl 访问是可以正常访问的,如下图：
+
+![avatar](/tutorial/pic/curl.png)
+
+总结：
+
+总体压测结果，虽然进程数只有8个，并且远端接口2秒才返回的情况。Qps 为185。因为是800并发，每个请求2秒，极限Qps应该是400
+
+这个结果比我想象的要低很多。估计需要优化。但是从这个压测结果可以观察出协程和传统php-fpm的区别还是很大的。传统php-fpm一般需要多开启很多个进程，一般服务器会开启128个进程，即使忽略php-fpm多进程对效率的影响。那么传统php-fpm能够提供的qps理论最大值，不会超过64个（因为每个请求是2秒返回，fpm进程会阻塞2秒）。
+
+压测结果中超时比较多。这个和系统task占用的cpu有关
+
+分析一下TOP命令的资源占用情况，例如第一个资源图。kernel_task占用的资源达到43%，相当高。不知道LINUX下面表现会不会更好
+
+kernel_task较高，应该是整个压测过程中  wrk nginx php-fpm nodejs  这4组程序的网络传输调度都是由它来搞定，比较繁忙
+
+php-fpm的cpu占用相对较低，说明调度都交给内核来执行了。这个符合协程的特性。
+
+图中，NODEJS占用18%左右，WRK占用10%
+
+nginx 占用cpu略低于php-fpm，换个角度来讲，php-fpm协程的性能已经接近于nginx
+
+最后，因为本机压测本机，服务也比较多。如果分开，效果会更好一些。
+
+
+## 注意事项
+
+
+1.请牢记这一点，php-fpm协程中，默认每个php-fpm进程的协程池大小为128个.超出的并发会等待。要想机器拥有更好的并发，请合理设置每进程的协程数，可以通过修改环境变量来配置。
+
+修改每个进程中协程池大小方法：
+
+首先切换到root账号，在环境变量中增加环境变量（PHP_COROUTINE_ENGINE_COUNT环境变量指定每个进程开启的协程数）
+```
+echo 'export PHP_COROUTINE_ENGINE_COUNT=1024' >> ~/.bash_profile
+source ~/.bash_profile
+```
+在/etc/sudoers中修改配置，用来支持sudo的环境变量传递： 
+```
+Defaults    env_reset 
+为： 
+Defaults    !env_reset
+```
+2.启动时，请注意调整好PHP-FPM进程数量,php-fpm.d/www.conf中
+```
+ pm = static  
+ pm.max_children = 4
+```
+3.注意,调整每个进程使用的内存大小.在php.ini中。请根据进程数量和系统可用内存合理计算
+```
+ memory_limit = 128M
+```
+4.测试时，请注意有些浏览器同一个链接是阻塞的，但是改变参数就不会阻塞了，例如chrome（这个比较坑，最开始我还以为是nginx的问题定位了很久）。建议使用curl命令测试，这样可以更好的观察协程效果
+
+## 扩展说明
+
+ext/coro_http 目录是为了测试协程开发的PHP扩展，提供了coro_http_get方法。  
+里面的核心文件是coro_http.c,已包含详尽的注释。  
+这个扩展可以当成一个协程实现的demo,里面内容非常简单，开发者可以参照demo开发更多支持协程的扩展。  
+因为php-fpm中调度器的部分已经实现，开发者只需要实现扩展即可开发协程应用。  
+
+目前只支持macOS和linux
+
+## 项目调试方法一，编译安装:
+
+
+1.系统中先要安装libevent库，具体安装方法请自行查找资料,另外可能还需要安装php需要的一些扩展
+
+2.生成automake配置文件
+```
+ sh buildconf --force
+```
+3.安装php
+```
+ ./configure --prefix=/usr/local/php7 --enable-fpm --enable-coro_http --enable-maintainer-zts && make && sudo make install
+```
+注意：linux 中需要增加--with-openssl ，不然安装会出错，mac不需要。  
+
+另外，因为好久没维护，发现MAC系统的iconv产生版本问题，可以在make的时候，替换Makefile中的-liconv成实际的地址即可。
+
+4.安装完成后修改php-fpm配置文件，设置PHP-FPM进程数。线上环境根据CPU数量和需要的协程数量调整，测试的时候可以设置成1（php-fpm.d/www.conf）
+主要是这两个参数
+``` 
+ pm = static   
+ pm.max_children = 1
+```
+5.启动php-fpm
+```
+ sudo /usr/local/php7/sbin/php-fpm
+```
+6.配置nginx，请自行查阅相关资料,请将nginx的访问目录配置成源码中的tutorial目录，主要是里面的test.php,用于测试
+
+7.以上不走完成了就可以开始测试了，根据配置好的NGINX，直接访问浏览器（注：mac里的chrome是不支持同一个url并发访问的。建议使用curl命令测试）  
+如果强烈要求使用chrome,请认真读下面的文字  
+例如：http://localhost/test.php?a=xx  
+这里一定要注意，在chrome中可以开两个窗口访问，但是后面的参数要不一样。  
+
+
+## 项目调试方法二，Docker hub安装[推荐]:
+1.拉取镜像
+```
+docker pull phpce/php-coroutine-engine  
+docker run --privileged --cpus=2 -e 'PHP_COROUTINE_ENGINE_COUNT=128' -p 8083:80 -v `pwd`:/data/www phpce/php-coroutine-engine
+```
+
+2.浏览器输入网址
+```
+ http://localhost:8083/test3.php
+```
+
+
+## 项目调试方法三，Docker build安装:
+
+1.进入项目根目录，执行:(如果在项目根目录执行过make ,请先执行make dist clean)
+```
+ docker build -t php-coroutine-engine -f tutorial/Dockerfile ./
+```
+2.运行docker:
+```
+ docker run --privileged --cpus=2 -e 'PHP_COROUTINE_ENGINE_COUNT=128' -p 8083:80 -v `pwd`/tutorial:/data/www php-coroutine-engine
+```
+3.浏览器输入网址
+```
+ http://localhost:8083/test3.php
+```
+可以看到输出结果为：
+```
+"window.baidu.sug({\"q\":\"\",\"p\":false,\"bs\":\"\",\"csor\":\"0\",\"status\":769,\"s\":[]});"
+```
+test3.php代码：
+```
+<?php
+echo json_encode(coro_http_get("http://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su"));
+?>
+```
+----------
+
+# Project description[For English]
+
+Project name phpce,full name php-coroutine-engine
+
+This project is a branch of php7 and has implemented PHP Native Coroutine.
+
+This project is a version from PHP's official GitHub fork, based on php7.1.17 version.
+
+Coopera is a design pattern that supports high concurrent servers.
+
+Now the mainstream server-side languages and frameworks support the call of the association Coroutine, including golang, openresty, Java, swoole and so on.
+
+Coroutine process can reduce server congestion, and the use of Coroutine process can significantly improve server performance for services such as RPC, mysql, redis, and other services that need to use remote calls.
+
+The nature of association Coroutine is one of the implementations of asynchronous asynchronous non blocking IO model.
+
+The traditional php-fpm design mode is mainly through concurrent processing requests through multiple processes. The use of server resources is inadequate.
+
+This project is through the transformation of the php-fpm source code, the implementation of the Coroutine model of the php-fpm, and finally, like nginx, several processes can deal with a large number of concurrent requests, full use of CPU resources, multiplied the performance of the PHP server.
+
+Note: this item has not been completely tested. Please be careful not to use it in the production environment.
+
+Author email :sioomy@qq.com ,if you have question ,send message to me.
+
+Finally, it's not easy to finish the project. Thank you for the support of the project and colleagues, especially the WorkerMan author worker, Chen Lei from didi, tongge who is the core developer of swoole, and my direct leader, hongjie. Next, we need to test in real applications and develop more extensions that support coroutine. I also hope that more developers will join in and give support and guidance.
+
+## Coroutine theory
+
+![avatar](/tutorial/pic/coroutine.jpg)
+
+The essence of the Coroutine is one of the asynchronous non blocking IO implementations. If php-fpm wants to implement the syndication, it needs to be divided into two parts, one is the scheduler, the other is to implement the syndication logic in the PHP extension.
+
+PHP-FPM is the role of the scheduler.
+
+When a request comes in, the scheduler triggers one execution. During the execution of this request, if a remote call is encountered in the PHP code, PHP automatically gives control to the scheduler after the request is sent. At this point, the scheduler can decide whether to handle other new incoming requests or to process requests that can be executed after the previous remote call.
+
+Each request is bound from a Coroutine process context from the Coroutine context pool, and after the request is finished, the coroutine process context is put back so that other requests can be reused.
+
+The context of the association mainly stores the global and private variables used in the PHP running environment. This implementation is mainly based on PHP's multithread secure storage (note not multithreading) and TSRM related library.
+
+The TSRM library will isolate all PHP global variables from macros and PHP memory pools.
+
+So when developing the extension of the coroutine, we should pay attention to the use of macro variables such as EG (), SG (), emalloc, EFREE and so on.
+
+The --enable-maintainer-zts parameter tells the compiler that it is required to support ZTS multithreaded secure storage.
+
+In multithread secure storage mode, the way of storing internal memory used by PHP can be generally understood as a matrix. The longitudinal axis of a matrix is each thread (coroutine). The horizontal axis of the matrix stores all the memory needed in all the running environments. That is to say, each PHP association has its own memory.
+
+The PHP version of the coda version uses multithread secure storage (TSRM). So the expansion of this version of php-fpm and the PHP code of application layer do not support multithreading.
+
+## Pressure test report
+
+The system has not been optimized. It will be optimized in the future
+
+The machine is 2016 MAC PRO, and the configuration is 2 cores, 8G memory.
+
+The test tool is wrk, and the command is as follows
+
+```
+./wrk -c 800 -t 800 -d 120s http://localhost/test.php
+```
+
+Open 800 threads, 800 connection presses, equivalent to 800 concurrent requests.
+
+In theory, each request is returned in 2 seconds, and the limit test result is 400qps.
+
+The request process is:
+
+```
+wrk >> nginx >> php-fpm >> nodejs
+```
+The wrk client accesses the NGINX FASTCGI reverse proxy, nginx visits php-fpm, and php-fpm visits the NODEJS program through the coroutine function.
+
+The nodejs program is on the 8080 port, simulating the interface that returns the result in 2 seconds.
+
+Test.js program location: tutorial/test.js
+
+The nodejs boot command:
+
+```
+Node tutorial/test.js
+```
+Test.php location: tutorial/test.php
+
+Test.php calls test.js through coro_http_get (HTTP client to implement the Association).
+
+```
+var_dump (coro_http_get ("http://localhost:8080/"));
+```
+In this test, php-fpm started 8 processes, and the maximum memory usage per process in PHP-FPM is 128M.
+
+NGINX started 8 processes
+
+The results of the test are as follows:
+
+![avatar](/tutorial/pic/rt.png)
+
+System occupancy capture 1:
+
+![avatar](/tutorial/pic/top1.png)
+
+System occupancy capture 2:
+
+![avatar](/tutorial/pic/top2.png)
+
+In the process of pressure measurement, access through curl can be accessed normally.
+
+![avatar](/tutorial/pic/curl.png)
+
+Summary:
+
+The overall test results, although the number of processes is only 8, and the remote interface 2 seconds to return. Qps is 185. Because it is 800 concurrent, each request for 2 seconds, the limit Qps should be 400.
+
+The result is much lower than I thought. It is estimated that it needs to be optimized. But from this measurement result, we can see that the difference between the coroutine and traditional php-fpm is still very different. Traditional php-fpm usually needs to open many more processes, and servers usually open 128 processes, even ignoring the impact of php-fpm multi-processes on efficiency. Then the maximum QPS theory that traditional php-fpm can provide is no more than 64 (because each request returns in 2 seconds, and the FPM process blocks for 2 seconds).
+
+The result of pressure measurement is more time-out. This is related to the CPU occupied by the system task
+
+Analyze the resource occupation of the TOP command, for example, the first resource map. Kernel_task takes up 43% of the resources, which is quite high. I don't know if the performance below LINUX will be better
+
+The kernel_task is higher, it should be wrk nginx php-fpm nodejs that the network transmission scheduling of these four groups of programs is done by it in the whole process of pressure measurement. It is busy.
+
+The CPU usage of php-fpm is relatively low, which means that the scheduling is handed over to the kernel for execution. This conforms to the characteristics of the co process.
+
+In the figure, NODEJS takes about 18% and WRK takes up 10%
+
+Nginx occupies CPU slightly below php-fpm. In another way, the performance of php-fpm is nearly nginx.
+
+Finally, because the machine presses the machine, there are more services. If separated, the effect would be better.
+
+
+
+
+## Matters of attention
+
+1. Keep this in mind. In php-fpm, the coroutine pool size of each php-fpm process is fixed to 128 by default. If you want the machine to have better concurrency, please configure the process number reasonably. you can set the coroutine number in environmental variables.
+
+Modify the coroutine pool size in each process:
+
+First,Checkout to root user,then add environmental variables in environmental variables(PHP_COROUTINE_ENGINE_COUNT is couroutine number in every process)
+```
+echo 'export PHP_COROUTINE_ENGINE_COUNT=1024' >> ~/.bash_profile
+
+source ~/.bash_profile
+
+```
+Modify configuration in /etc/sudoers to support sudo's environment variable delivery:
+```
+Defaults env_reset
+```
+For:
+```
+Defaults! Env_reset
+```
+
+2. when starting, pay attention to adjusting the number of PHP-FPM processes, php-fpm.d/www.conf
+
+```
+pm = static  
+pm.max_children = 4
+```
+
+3. note that adjust the memory size used by each process. In php.ini. Please calculate reasonably according to the number of processes and the available memory of the system.
+
+```
+memory_limit = 128M
+```
+
+4. when testing, please note that some browsers are blocking the same link, but changing the parameters will not block, such as chrome (this comparison pit, at first I think it's a long time to think it's nginx's problem). It is recommended that the curl command test be used to better observe the synergy effect.
+
+## Extension explanation
+
+The ext/coro_http directory provides a coro_http_get method for testing the PHP extension of the co development.
+
+The core document is coro_http.c, which contains detailed annotations.
+
+This extension can be thought of as a demo for the implementation of a collaboration, which is very simple, and developers can develop more extensions to support the collaboration with the help of demo.
+
+Because the part of scheduler in php-fpm has been implemented, developers only need to extend it to develop cooperating applications.
+
+Only macOS and Linux are currently supported
+
+## Debug method 1, compile and install:
+
+1. Install libevent libraries in the system first. Find out how to install libevent libraries by yourself, and you may also need to install some extensions required by PHP
+
+2. generate automake configuration file
+
+```
+sh buildconf --force
+```
+3. install PHP
+
+```
+./configure --prefix=/usr/local/php7 --enable-fpm --enable-coro_http --enable-maintainer-zts && make && sudo make install
+```
+
+Note: --with-openssl is needed in Linux, otherwise installation will be wrong and Mac will not be needed.
+
+4. after installation, modify the php-fpm configuration file and set the number of PHP-FPM processes. The online environment can be adjusted to 1 (php-fpm.d/www.conf) according to the number of CPU and the number of required cooperations.
+
+This is mainly the two parameters
+
+```
+pm = static  
+pm.max_children = 1
+```
+
+5. start php-fpm
+
+```
+sudo /usr/local/php7/sbin/php-fpm
+```
+
+6. Configuration of nginx, please consult the relevant information, please configure the nginx access directory into the source code tutorial directory, mainly the test. php, for testing
+
+7. You can start the test without completing it. According to the configured NGINX, access the browser directly (Note: the chrome in MAC does not support the same URL concurrent access. It is recommended to use the curl command test)
+
+If you strongly request the use of chrome, please read the following text carefully.
+
+For example, http://localhost/test.php?a=xx
+
+It is important to note that in chrome, two windows can be accessed, but the following parameters are different.
+
+
+## Debug method two，Docker hub installation[recommended]:
+1.pull images from docker hub
+```
+docker pull phpce/php-coroutine-engine  
+docker run --privileged --cpus=2 -e 'PHP_COROUTINE_ENGINE_COUNT=128' -p 8083:80  -v `pwd`:/data/www phpce/php-coroutine-engine
+```
+
+2.browsers enter the URL
+```
+ http://localhost:8083/test3.php
+```
+
+## Debug method three, Docker build installation:
+
+
+
+1. enter root dir of project, execute:(if you had make in this dir please run make dist clean)
+
+```
+ docker build -t php-coroutine-engine -f tutorial/Dockerfile ./
+```
+
+2. run docker:
+
+```
+docker run --privileged --cpus=2 -e 'PHP_COROUTINE_ENGINE_COUNT=128' -p 8083:80 -v `pwd`/tutorial:/data/www php-coroutine-engine
+```
+
+3. browsers enter the URL
+
+```
+http://localhost:8083/test3.php
+```
+
+It can be seen that the output results are as follows:
+
+```
+"window.baidu.sug({\"q\":\"\",\"p\":false,\"bs\":\"\",\"csor\":\"0\",\"status\":769,\"s\":[]});"
+```
+
+Test3.php Code:
+
+```
+<?php
+echo json_encode(coro_http_get("http://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su"));
+?>
+```
 
diff --git a/README_PHP.md b/README_PHP.md
new file mode 100644
index 00000000000..c5379f19116
--- /dev/null
+++ b/README_PHP.md
@@ -0,0 +1,40 @@
+
+The PHP Interpreter
+===================
+This is the github mirror of the official PHP repository located at
+http://git.php.net.
+
+[![Build Status](https://secure.travis-ci.org/php/php-src.svg?branch=master)](http://travis-ci.org/php/php-src)
+[![Build status](https://ci.appveyor.com/api/projects/status/meyur6fviaxgdwdy?svg=true)](https://ci.appveyor.com/project/php/php-src)
+
+Pull Requests
+=============
+PHP accepts pull requests via github. Discussions are done on github, but
+depending on the topic can also be relayed to the official PHP developer
+mailing list internals@lists.php.net.
+
+New features require an RFC and must be accepted by the developers.
+See https://wiki.php.net/rfc and https://wiki.php.net/rfc/voting for more
+information on the process.
+
+Bug fixes **do not** require an RFC, but require a bugtracker ticket. Always
+open a ticket at https://bugs.php.net and reference the bug id using #NNNNNN.
+
+    Fix #55371: get_magic_quotes_gpc() throws deprecation warning
+
+    After removing magic quotes, the get_magic_quotes_gpc function caused
+    a deprecate warning. get_magic_quotes_gpc can be used to detected
+    the magic_quotes behavior and therefore should not raise a warning at any
+    time. The patch removes this warning
+
+We do not merge pull requests directly on github. All PRs will be
+pulled and pushed through http://git.php.net.
+
+
+Guidelines for contributors
+===========================
+- [CODING_STANDARDS](/CODING_STANDARDS)
+- [README.GIT-RULES](/README.GIT-RULES)
+- [README.MAILINGLIST_RULES](/README.MAILINGLIST_RULES)
+- [README.RELEASE_PROCESS](/README.RELEASE_PROCESS)
+
diff --git a/TSRM/TSRM.c b/TSRM/TSRM.c
index 9fb8abd3a4d..14f224934d3 100644
--- a/TSRM/TSRM.c
+++ b/TSRM/TSRM.c
@@ -29,6 +29,7 @@ typedef struct _tsrm_tls_entry tsrm_tls_entry;
 struct _tsrm_tls_entry {
 	void **storage;
 	int count;
+	ts_rsrc_id rsrc_id;
 	THREAD_T thread_id;
 	tsrm_tls_entry *next;
 };
@@ -42,9 +43,49 @@ typedef struct {
 } tsrm_resource_type;
 
 
+typedef struct _rsrc_id_map_link rsrc_id_map_link;
+struct _rsrc_id_map_link {
+	intptr_t value;
+	rsrc_id_map_link *next;
+};
+int rsrc_id_map_size = 100;
+rsrc_id_map_link** rsrc_id_map;
+
+//用于存储rsrc_id
+/* 从hashtable中查找rsrc_id地址，确认是否为新的（未使用过） */
+int rsrc_id_set_isnew(intptr_t rsrc_id_ptr){
+	int hash_value = THREAD_HASH_OF(rsrc_id_ptr,rsrc_id_map_size);
+
+	rsrc_id_map_link* link = rsrc_id_map[hash_value];
+
+	while(link){
+		if(link->value == rsrc_id_ptr){
+			return 0;
+		}else if(link->next){//有后续
+			link = link->next;
+		}else{//无后续
+			break;
+		}
+	}
+
+	//写入
+	rsrc_id_map_link* new_link = malloc(sizeof(rsrc_id_map_link));
+	new_link->next = NULL;
+	new_link->value = rsrc_id_ptr;
+	if(link){
+		link->next = new_link;
+	}else{
+		rsrc_id_map[hash_value] = new_link;
+	}
+
+	return 1;
+}
+
+
 /* The memory manager table */
 static tsrm_tls_entry	**tsrm_tls_table=NULL;
 static int				tsrm_tls_table_size;
+static int 				force_thread_id = -1;//这个值不等于-1，代表协程状态
 static ts_rsrc_id		id_count;
 
 /* The resource sizes table */
@@ -128,6 +169,7 @@ static int32 tls_key;
 /* Startup TSRM (call once for the entire process) */
 TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename)
 {
+	rsrc_id_map = (rsrc_id_map_link**) calloc(rsrc_id_map_size,sizeof(rsrc_id_map_link*));
 #if defined(GNUPTH)
 	pth_init();
 	pth_key_create(&tls_key, 0);
@@ -220,10 +262,35 @@ TSRM_API void tsrm_shutdown(void)
 #endif
 }
 
+TSRM_API void set_force_thread_id(int thread_id){
+	force_thread_id = thread_id;
+}
+
+TSRM_API int get_force_thread_id(void){
+	return force_thread_id;
+}
 
 /* allocates a new thread-safe-resource id */
 TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
 {
+	int isnew = rsrc_id_set_isnew((intptr_t)rsrc_id);
+	if(!isnew){
+		/**
+		 * 这里需要注意的逻辑调整:
+		 * ts_allocate_id函数在当同一个rsrc_id（通过相同内存地址判断）第一次执行的时候，会为所有协程分配内存
+		 * 但只会为当前协程/线程执行构造函数初始化数据
+		 * 当不是第一次调用的时候，会为当前协程/线程初始化数据。
+		 * 当所有协程都执行一遍，才会全部初始化完毕。
+		 * 这个特性主要针对在多协程/线程调用ts_allocate_id的时候，有些初始化方法会使用线程安全存储，
+		 * 若只在一个协程里调用会导致初始化不完整
+		 */
+		tsrm_tls_entry *p = tsrm_tls_table[force_thread_id];
+		if (resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor) {//只初始化当前协程
+			resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor(p->storage[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)]);
+		}
+		return *rsrc_id;
+	}
+
 	int i;
 
 	TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new resource id, %d bytes", size));
@@ -261,7 +328,7 @@ TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate
 				p->storage = (void *) realloc(p->storage, sizeof(void *)*id_count);
 				for (j=p->count; j<id_count; j++) {
 					p->storage[j] = (void *) malloc(resource_types_table[j].size);
-					if (resource_types_table[j].ctor) {
+					if (resource_types_table[j].ctor && (force_thread_id == -1 || force_thread_id == i)) {//只初始化当前协程
 						resource_types_table[j].ctor(p->storage[j]);
 					}
 				}
@@ -450,6 +517,24 @@ void *tsrm_new_interpreter_context(void)
 	return tsrm_set_interpreter_context(current);
 }
 
+/* allocates a new interpreter context */
+void create_tsrm_tls_entry(int idx)
+{
+	set_force_thread_id(idx);
+	tsrm_tls_table[idx] = tsrm_new_interpreter_context();
+}
+
+/* allocates a new interpreter context */
+void *get_tsrm_tls_entry(int idx)
+{
+	if(idx>=tsrm_tls_table_size)return NULL;
+
+	tsrm_tls_entry *p = tsrm_tls_table[idx];
+	/* switch back to the context that was in use prior to our creation
+	 * of the new one */
+	return p;
+}
+
 
 /* frees all resources allocated for the current thread */
 void ts_free_thread(void)
@@ -582,6 +667,9 @@ void ts_free_id(ts_rsrc_id id)
 /* Obtain the current thread id */
 TSRM_API THREAD_T tsrm_thread_id(void)
 {
+	if(force_thread_id != -1){
+		return (THREAD_T)force_thread_id;
+	}
 #ifdef TSRM_WIN32
 	return GetCurrentThreadId();
 #elif defined(GNUPTH)
diff --git a/TSRM/TSRM.h b/TSRM/TSRM.h
index 458843a689a..3b19aa07264 100644
--- a/TSRM/TSRM.h
+++ b/TSRM/TSRM.h
@@ -149,6 +149,10 @@ TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread
 /* these 3 APIs should only be used by people that fully understand the threading model
  * used by PHP/Zend and the selected SAPI. */
 TSRM_API void *tsrm_new_interpreter_context(void);
+TSRM_API void *get_tsrm_tls_entry(int idx);
+TSRM_API void create_tsrm_tls_entry(int idx);
+TSRM_API void set_force_thread_id(int thread_id);
+TSRM_API int get_force_thread_id(void);
 TSRM_API void *tsrm_set_interpreter_context(void *new_ctx);
 TSRM_API void tsrm_free_interpreter_context(void *context);
 
@@ -173,13 +177,17 @@ TSRM_API void *tsrm_get_ls_cache(void);
 #define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE;
 #define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE = NULL;
 #if ZEND_DEBUG
-#define TSRMLS_CACHE_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache()
+// #define TSRMLS_CACHE_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache()
+#define TSRMLS_CACHE_UPDATE()
 #define TSRMLS_CACHE_RESET()
 #else
-#define TSRMLS_CACHE_UPDATE() if (!TSRMLS_CACHE) TSRMLS_CACHE = tsrm_get_ls_cache()
-#define TSRMLS_CACHE_RESET()  TSRMLS_CACHE = NULL
+// #define TSRMLS_CACHE_UPDATE() if (!TSRMLS_CACHE) TSRMLS_CACHE = tsrm_get_ls_cache()
+#define TSRMLS_CACHE_UPDATE()
+// #define TSRMLS_CACHE_RESET()  TSRMLS_CACHE = NULL
+#define TSRMLS_CACHE_RESET()
 #endif
-#define TSRMLS_CACHE _tsrm_ls_cache
+// #define TSRMLS_CACHE _tsrm_ls_cache
+#define TSRMLS_CACHE tsrm_get_ls_cache()
 
 /* BC only */
 #define TSRMLS_D void
diff --git a/Zend/zend.c b/Zend/zend.c
index 15cab8048ff..29ac188f299 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -554,8 +554,14 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{
 {
 	ZEND_TSRMLS_CACHE_UPDATE();
 
+#ifdef ZTS
+	executor_globals->zend_constants = (HashTable *) malloc(sizeof(HashTable));
+	zend_hash_init(executor_globals->zend_constants, 128, NULL, ZEND_CONSTANT_DTOR, 1);
+	zend_copy_constants(executor_globals->zend_constants, GLOBAL_CONSTANTS_TABLE);
+#else
 	zend_startup_constants();
 	zend_copy_constants(EG(zend_constants), GLOBAL_CONSTANTS_TABLE);
+#endif
 	zend_init_rsrc_plist();
 	zend_init_exception_op();
 	zend_init_call_trampoline_op();
diff --git a/Zend/zend.h b/Zend/zend.h
index 35d518ca8f5..b44066c05f3 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -53,19 +53,19 @@
 	 !ZEND_USER_CODE(EX(prev_execute_data)->func->common.type) || \
 	 (EX(prev_execute_data)->opline->result_type != IS_UNUSED))
 
-#ifdef ZEND_ENABLE_STATIC_TSRMLS_CACHE
-#define ZEND_TSRMG TSRMG_STATIC
-#define ZEND_TSRMLS_CACHE_EXTERN() TSRMLS_CACHE_EXTERN()
-#define ZEND_TSRMLS_CACHE_DEFINE() TSRMLS_CACHE_DEFINE()
-#define ZEND_TSRMLS_CACHE_UPDATE() TSRMLS_CACHE_UPDATE()
-#define ZEND_TSRMLS_CACHE TSRMLS_CACHE
-#else
+// #ifdef ZEND_ENABLE_STATIC_TSRMLS_CACHE
+// #define ZEND_TSRMG TSRMG_STATIC
+// #define ZEND_TSRMLS_CACHE_EXTERN() TSRMLS_CACHE_EXTERN()
+// #define ZEND_TSRMLS_CACHE_DEFINE() TSRMLS_CACHE_DEFINE()
+// #define ZEND_TSRMLS_CACHE_UPDATE() TSRMLS_CACHE_UPDATE()
+// #define ZEND_TSRMLS_CACHE TSRMLS_CACHE
+// #else
 #define ZEND_TSRMG TSRMG
 #define ZEND_TSRMLS_CACHE_EXTERN()
 #define ZEND_TSRMLS_CACHE_DEFINE()
 #define ZEND_TSRMLS_CACHE_UPDATE()
-#define ZEND_TSRMLS_CACHE
-#endif
+#define ZEND_TSRMLS_CACHE 
+// #endif
 
 ZEND_TSRMLS_CACHE_EXTERN()
 
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 60e2960afcc..abbea4eac76 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -1793,6 +1793,39 @@ ZEND_API int add_property_zval_ex(zval *arg, const char *key, size_t key_len, zv
 }
 /* }}} */
 
+ZEND_API int zend_startup_module_ex2(zend_module_entry *module) /* {{{ */
+{
+	size_t name_len;
+	zend_string *lcname;
+
+	if (module->module_started) {
+		return SUCCESS;
+	}
+	module->module_started = 1;
+
+	/* Initialize module globals */
+	if (module->globals_size) {
+#ifdef ZTS
+		ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
+#else
+		if (module->globals_ctor) {
+			module->globals_ctor(module->globals_ptr);
+		}
+#endif
+	}
+	if (module->module_startup_func) {
+		EG(current_module) = module;
+		if (module->module_startup_func(module->type, module->module_number)==FAILURE) {
+			zend_error_noreturn(E_CORE_ERROR,"Unable to start %s module", module->name);
+			EG(current_module) = NULL;
+			return FAILURE;
+		}
+		EG(current_module) = NULL;
+	}
+	return SUCCESS;
+}
+/* }}} */
+
 ZEND_API int zend_startup_module_ex(zend_module_entry *module) /* {{{ */
 {
 	size_t name_len;
@@ -1851,10 +1884,16 @@ ZEND_API int zend_startup_module_ex(zend_module_entry *module) /* {{{ */
 }
 /* }}} */
 
-static int zend_startup_module_zval(zval *zv) /* {{{ */
+static int zend_startup_module_zval2(zval *zv) /* {{{ */
 {
 	zend_module_entry *module = Z_PTR_P(zv);
+	zend_startup_module_ex2(module);
+	return ZEND_HASH_APPLY_KEEP;
+}
 
+static int zend_startup_module_zval(zval *zv) /* {{{ */
+{
+	zend_module_entry *module = Z_PTR_P(zv);
 	return (zend_startup_module_ex(module) == SUCCESS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
 }
 /* }}} */
@@ -1966,7 +2005,17 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
 ZEND_API int zend_startup_modules(void) /* {{{ */
 {
 	zend_hash_sort_ex(&module_registry, zend_sort_modules, NULL, 0);
-	zend_hash_apply(&module_registry, zend_startup_module_zval);
+	zend_module_entry *mob;
+	ZEND_HASH_FOREACH_PTR(&module_registry, mob) {
+		// fprintf(stderr, "-----in  ---- zend_hash_apply----module_ptr:%d,name:%s,globals_size:%d,nNumUsed:%d\n",mob,mob->name,mob->globals_size,module_registry.nNumUsed );
+	} ZEND_HASH_FOREACH_END();
+
+	// if(get_force_thread_id()>0){
+	// 	zend_hash_apply(&module_registry, zend_startup_module_zval2);
+	// }else{
+		zend_hash_apply(&module_registry, zend_startup_module_zval);
+	// }
+
 	return SUCCESS;
 }
 /* }}} */
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index dc443838553..e8f3e478a63 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -1517,7 +1517,6 @@ ZEND_API void ZEND_FASTCALL zend_hash_apply(HashTable *ht, apply_func_t apply_fu
 	HASH_UNPROTECT_RECURSION(ht);
 }
 
-
 ZEND_API void ZEND_FASTCALL zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument)
 {
     uint32_t idx;
diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c
index ae1a8674603..0b8c8d82fef 100644
--- a/Zend/zend_virtual_cwd.c
+++ b/Zend/zend_virtual_cwd.c
@@ -515,14 +515,18 @@ CWD_API void virtual_cwd_startup(void) /* {{{ */
 
 CWD_API void virtual_cwd_shutdown(void) /* {{{ */
 {
-#ifndef ZTS
+#ifdef ZTS
+	cwd_globals_dtor(ts_resource(cwd_globals_id));
+#else
 	cwd_globals_dtor(&cwd_globals);
 #endif
 #if (defined(ZEND_WIN32) || defined(NETWARE)) && defined(ZTS)
 	tsrm_mutex_free(cwd_mutex);
 #endif
-
+// #ifndef ZTS
 	free(main_cwd_state.cwd); /* Don't use CWD_STATE_FREE because the non global states will probably use emalloc()/efree() */
+	// main_cwd_state.cwd = NULL;
+// #endif
 }
 /* }}} */
 
diff --git a/ext/coro_http/.gitignore b/ext/coro_http/.gitignore
new file mode 100644
index 00000000000..2bdbb49553c
--- /dev/null
+++ b/ext/coro_http/.gitignore
@@ -0,0 +1,35 @@
+.deps
+*.lo
+*.la
+.libs
+acinclude.m4
+aclocal.m4
+autom4te.cache
+build
+config.guess
+config.h
+config.h.in
+config.log
+config.nice
+config.status
+config.sub
+configure
+configure.in
+include
+install-sh
+libtool
+ltmain.sh
+Makefile
+Makefile.fragments
+Makefile.global
+Makefile.objects
+missing
+mkinstalldirs
+modules
+run-tests.php
+tests/*/*.diff
+tests/*/*.out
+tests/*/*.php
+tests/*/*.exp
+tests/*/*.log
+tests/*/*.sh
diff --git a/ext/coro_http/CREDITS b/ext/coro_http/CREDITS
new file mode 100644
index 00000000000..ad036ea6d1b
--- /dev/null
+++ b/ext/coro_http/CREDITS
@@ -0,0 +1 @@
+coro_http
diff --git a/ext/coro_http/EXPERIMENTAL b/ext/coro_http/EXPERIMENTAL
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/ext/coro_http/config.m4 b/ext/coro_http/config.m4
new file mode 100644
index 00000000000..db131780bee
--- /dev/null
+++ b/ext/coro_http/config.m4
@@ -0,0 +1,63 @@
+dnl $Id$
+dnl config.m4 for extension coro_http
+
+dnl Comments in this file start with the string 'dnl'.
+dnl Remove where necessary. This file will not work
+dnl without editing.
+
+dnl If your extension references something external, use with:
+
+PHP_ARG_WITH(coro_http, for coro_http support,
+dnl Make sure that the comment is aligned:
+[  --with-coro_http             Include coro_http support])
+
+dnl Otherwise use enable:
+
+PHP_ARG_ENABLE(coro_http, whether to enable coro_http support,
+dnl Make sure that the comment is aligned:
+[  --enable-coro_http           Enable coro_http support])
+
+if test "$PHP_CORO_HTTP" != "no"; then
+  dnl Write more examples of tests here...
+
+  dnl # --with-coro_http -> check with-path
+  dnl SEARCH_PATH="/usr/local /usr"     # you might want to change this
+  dnl SEARCH_FOR="/include/coro_http.h"  # you most likely want to change this
+  dnl if test -r $PHP_CORO_HTTP/$SEARCH_FOR; then # path given as parameter
+  dnl   CORO_HTTP_DIR=$PHP_CORO_HTTP
+  dnl else # search default path list
+  dnl   AC_MSG_CHECKING([for coro_http files in default path])
+  dnl   for i in $SEARCH_PATH ; do
+  dnl     if test -r $i/$SEARCH_FOR; then
+  dnl       CORO_HTTP_DIR=$i
+  dnl       AC_MSG_RESULT(found in $i)
+  dnl     fi
+  dnl   done
+  dnl fi
+  dnl
+  dnl if test -z "$CORO_HTTP_DIR"; then
+  dnl   AC_MSG_RESULT([not found])
+  dnl   AC_MSG_ERROR([Please reinstall the coro_http distribution])
+  dnl fi
+
+  dnl # --with-coro_http -> add include path
+  dnl PHP_ADD_INCLUDE($CORO_HTTP_DIR/include)
+
+  dnl # --with-coro_http -> check for lib and symbol presence
+  dnl LIBNAME=coro_http # you may want to change this
+  dnl LIBSYMBOL=coro_http # you most likely want to change this 
+
+  dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
+  dnl [
+  dnl   PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $CORO_HTTP_DIR/$PHP_LIBDIR, CORO_HTTP_SHARED_LIBADD)
+  dnl   AC_DEFINE(HAVE_CORO_HTTPLIB,1,[ ])
+  dnl ],[
+  dnl   AC_MSG_ERROR([wrong coro_http lib version or lib not found])
+  dnl ],[
+  dnl   -L$CORO_HTTP_DIR/$PHP_LIBDIR -lm
+  dnl ])
+  dnl
+  dnl PHP_SUBST(CORO_HTTP_SHARED_LIBADD)
+
+  PHP_NEW_EXTENSION(coro_http, coro_http.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
+fi
diff --git a/ext/coro_http/config.w32 b/ext/coro_http/config.w32
new file mode 100644
index 00000000000..7c1257269ba
--- /dev/null
+++ b/ext/coro_http/config.w32
@@ -0,0 +1,13 @@
+// $Id$
+// vim:ft=javascript
+
+// If your extension references something external, use ARG_WITH
+// ARG_WITH("coro_http", "for coro_http support", "no");
+
+// Otherwise, use ARG_ENABLE
+// ARG_ENABLE("coro_http", "enable coro_http support", "no");
+
+if (PHP_CORO_HTTP != "no") {
+	EXTENSION("coro_http", "coro_http.c", PHP_EXTNAME_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
+}
+
diff --git a/ext/coro_http/coro_http.c b/ext/coro_http/coro_http.c
new file mode 100644
index 00000000000..b01a334d3ee
--- /dev/null
+++ b/ext/coro_http/coro_http.c
@@ -0,0 +1,578 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 7                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2018 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Author:                                                              |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "php_coro_http.h"
+
+#include "SAPI.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/queue.h>
+
+#include "event2/http.h"
+#include "event2/http_struct.h"
+#include "event2/event.h"
+#include "event2/buffer.h"
+#include "event2/dns.h"
+#include "event2/thread.h"
+#include <event.h>
+#include <event2/bufferevent.h>
+
+#include "ext/standard/fpm_coroutine.h"
+
+#ifndef WIN32  
+#include <sys/socket.h>  
+#include <sys/types.h>  
+#include <netinet/in.h>  
+#include <arpa/inet.h>  
+#endif  
+
+
+
+/* If you declare any globals in php_coro_http.h uncomment this:
+ZEND_DECLARE_MODULE_GLOBALS(coro_http)
+*/
+
+/* True global resources - no need for thread safety here */
+static int le_coro_http;
+
+typedef struct _coro_http_param
+{
+    struct evhttp_connection* connection;
+    struct evhttp_uri* uri;
+    sapi_coroutine_context* context;
+} coro_http_param;
+
+
+
+/************************************************************************
+ *   扩展需要用到的member
+ *   SG(coroutine_info).get_event_base();                                   基础event_loop_base
+ *   SG(coroutine_info).context                                 上下文
+ *   SG(coroutine_info).tmpData                                 是一个void* 类型的空指针，用于临时存放数据
+ *   SG(coroutine_info).test_log(char* str);                    输出LOG
+ *   SG(coroutine_info).yield_coroutine_context();              释放当前协程
+ *   SG(coroutine_info).checkout_coroutine_context(context);    切换到协程
+ *   SG(coroutine_info).resume_coroutine_context();             继续执行上下文
+ */
+
+void free_request(coro_http_param* http_param){
+    // evhttp_connection_free(http_param->connection);
+    evhttp_connection_free_on_completion(http_param->connection);
+    evhttp_uri_free(http_param->uri);
+    efree(http_param);
+}
+
+int ReadHeaderDoneCallback(struct evhttp_request* remote_rsp, void* arg)
+{
+    sapi_coroutine_context* context = ((coro_http_param*)arg)->context;
+    SG(coroutine_info).checkout_coroutine_context(context);
+
+    char txt[1024];
+    sprintf(txt, "< HTTP/1.1 %d %s\n", evhttp_request_get_response_code(remote_rsp), evhttp_request_get_response_code_line(remote_rsp));
+    struct evkeyvalq* headers = evhttp_request_get_input_headers(remote_rsp);
+    // struct evkeyval* header;
+    // TAILQ_FOREACH(header, headers, next)
+    // {
+    //     fprintf(stderr, "< %s: %s\n", header->key, header->value);
+    // }
+    // fprintf(stderr, "< \n");
+    // SG(coroutine_info).test_log(txt);
+}
+
+void ReadChunkCallback(struct evhttp_request* remote_rsp, void* arg)
+{
+    sapi_coroutine_context* context = ((coro_http_param*)arg)->context;
+    SG(coroutine_info).checkout_coroutine_context(context);
+
+    char* tmpStr = (char*)context->tmpData;
+    char buf[1024];
+    struct evbuffer* evbuf = evhttp_request_get_input_buffer(remote_rsp);
+    int n = 0;
+    while ((n = evbuffer_remove(evbuf, buf, 1024)) > 0)
+    {
+        strncat(tmpStr,buf,n);
+    }
+}
+
+void RemoteReadCallback(struct evhttp_request* remote_rsp, void* arg)
+{
+    /**
+     * 当远程调用成功，立刻切换协程，arg是evhttp新建请求时传递过来的协程context
+     * 这里注意，一定要第一时间切换到当前请求的context
+     * 这样才能保证emalloc、SG宏、EG宏，等全局宏可以正确拿到当前协程的内存
+     */
+    sapi_coroutine_context* context = ((coro_http_param*)arg)->context;
+    SG(coroutine_info).checkout_coroutine_context(context);
+
+    // bufferevent_free(remote_rsp);
+
+    /**
+     * tmpStatus为0代表正常有结果，否则代表请求出错。返回值已被设置成错误提示
+     */
+    char* tmpStr = (char*)context->tmpData;
+
+    /**
+     * return_value 是扩展函数执行时保存下来的返回值指针
+     */
+    zval* return_value = context->return_value;
+
+    /**
+     * 从全局变量中获取返回结果的buffer,并创建zend_string类型的结果
+     */
+    zend_string* result = zend_string_init(tmpStr,strlen(tmpStr)*sizeof(char),0);
+
+    /**
+     * 设置函数返回值
+     */
+    RETVAL_STR(result);
+    efree(tmpStr);
+    context->tmpData = NULL;
+    free_request(arg);
+
+
+    // SG(coroutine_info).test_log("request done\n");
+
+    /**
+     * 继续执行当前协程的PHP脚本
+     */
+    SG(coroutine_info).resume_coroutine_context();
+}
+
+void RemoteRequestErrorCallback(enum evhttp_request_error error, void* arg)
+{
+    sapi_coroutine_context* context = ((coro_http_param*)arg)->context;
+    SG(coroutine_info).checkout_coroutine_context(context);
+    char* tmpStr = (char*)context->tmpData;
+    switch(error){
+        case EVREQ_HTTP_TIMEOUT:
+            strncat(tmpStr,"remote request error:EVREQ_HTTP_TIMEOUT!",strlen("remote request error:EVREQ_HTTP_TIMEOUT!")*sizeof(char));
+            break;
+        case EVREQ_HTTP_EOF:
+            strncat(tmpStr,"remote request error:EVREQ_HTTP_EOF!",strlen("remote request error:EVREQ_HTTP_EOF!")*sizeof(char));
+            break;
+        case EVREQ_HTTP_INVALID_HEADER:
+            strncat(tmpStr,"remote request error:EVREQ_HTTP_INVALID_HEADER!",strlen("remote request error:EVREQ_HTTP_INVALID_HEADER!")*sizeof(char));
+            break;
+        case EVREQ_HTTP_BUFFER_ERROR:
+            strncat(tmpStr,"remote request error:EVREQ_HTTP_BUFFER_ERROR!",strlen("remote request error:EVREQ_HTTP_BUFFER_ERROR!")*sizeof(char));
+            break;
+        case EVREQ_HTTP_REQUEST_CANCEL:
+            strncat(tmpStr,"remote request error:EVREQ_HTTP_REQUEST_CANCEL!",strlen("remote request error:EVREQ_HTTP_REQUEST_CANCEL!")*sizeof(char));
+            break;
+        case EVREQ_HTTP_DATA_TOO_LONG:
+            strncat(tmpStr,"remote request error:EVREQ_HTTP_DATA_TOO_LONG!",strlen("remote request error:EVREQ_HTTP_DATA_TOO_LONG!")*sizeof(char));
+            break;
+        default:
+            strncat(tmpStr,"remote request error:unkown error!",strlen("remote request error:unkown error!")*sizeof(char));
+            break;
+    }
+}
+
+void RemoteConnectionCloseCallback(struct evhttp_connection* connection, void* arg)
+{
+    // test_log("=== evhttp connection close ===\n");
+}
+
+/* {{{ PHP_INI
+ */
+/* Remove comments and fill if you need to have entries in php.ini
+PHP_INI_BEGIN()
+    STD_PHP_INI_ENTRY("coro_http.global_value",      "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_coro_http_globals, coro_http_globals)
+    STD_PHP_INI_ENTRY("coro_http.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_coro_http_globals, coro_http_globals)
+PHP_INI_END()
+*/
+/* }}} */
+
+/* Remove the following function when you have successfully modified config.m4
+   so that your module can be compiled into PHP, it exists only for testing
+   purposes. */
+
+/* Every user-visible function in PHP should document itself in the source */
+/* {{{ proto string confirm_coro_http_compiled(string arg)
+   Return a string to confirm that the module is compiled in */
+PHP_FUNCTION(coro_http_get)
+{
+    /**
+     * 保存coro_http_get返回值指针到协程中，当evhttp返回时会用到
+     */
+    SG(coroutine_info).context->return_value = return_value; 
+
+    zval* param;
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &param) == FAILURE){
+        zend_string* result = zend_string_init("param error!",strlen("param error!")*sizeof(char),0);
+        RETURN_STR(result);
+    }
+    char* url = ZSTR_VAL(zval_get_string(param));
+    coro_http_param* coro_param = emalloc(sizeof(coro_http_param));
+    struct evhttp_uri* uri = evhttp_uri_parse(url);
+    coro_param->context = SG(coroutine_info).context;
+    coro_param->uri = uri;
+
+    if (!uri)
+    {
+        zend_string* result = zend_string_init("uri create error!",strlen("uri create error!")*sizeof(char),0);
+        RETURN_STR(result);
+    }
+
+    /**
+     * 这里与正常使用evhttp不同的是，要使用协程里的event_base，并且后面不需要调用loop方法（使用系统的loop）
+     */
+    struct event_base *base = SG(coroutine_info).get_event_base();
+
+    if (!base)
+    {
+        zend_string* result = zend_string_init("event_base error!",strlen("event_base error!")*sizeof(char),0);
+        RETURN_STR(result);
+    }
+
+    struct evdns_base* dnsbase = SG(coroutine_info).get_evdns_base(); 
+    if (!dnsbase)
+    {
+        zend_string* result = zend_string_init("dnsbase error!",strlen("dnsbase error!")*sizeof(char),0);
+        RETURN_STR(result);
+
+    }
+    assert(dnsbase);
+    
+    char* tmpStr = (char*)emalloc(sizeof(char)*4096);
+    strcpy(tmpStr,"");
+    /**
+     * 注意，tmpStr是不能放在全局里的，因为多个协程操作会导致不安全
+     * 因此，tmpStr放在上下文里比较好
+     */
+    SG(coroutine_info).context->tmpData = (void*)tmpStr;
+
+    struct evhttp_request* request = evhttp_request_new(RemoteReadCallback, coro_param);
+    evhttp_request_set_header_cb(request, ReadHeaderDoneCallback);
+    evhttp_request_set_chunked_cb(request, ReadChunkCallback);
+    evhttp_request_set_error_cb(request, RemoteRequestErrorCallback);
+    
+    const char* host = evhttp_uri_get_host(uri);
+    if (!host)
+    {
+        zend_string* result = zend_string_init("host error!",strlen("host error!")*sizeof(char),0);
+        RETURN_STR(result);
+    }
+
+    int port = evhttp_uri_get_port(uri);
+    if (port < 0) port = 80;
+
+    const char* request_url = url;
+    const char* path = evhttp_uri_get_path(uri);
+    if (path == NULL || strlen(path) == 0)
+    {
+        request_url = "/";
+    }
+
+    struct evhttp_connection* connection =  evhttp_connection_base_new(base, dnsbase, host, port);
+    if (!connection)
+    {
+        zend_string* result = zend_string_init("create connection error!",strlen("create connection error!")*sizeof(char),0);
+        RETURN_STR(result);
+    }
+    coro_param->connection = connection;
+    evhttp_connection_set_closecb(connection, RemoteConnectionCloseCallback, base);
+    evhttp_add_header(evhttp_request_get_output_headers(request), "Host", host);
+
+    evhttp_make_request(connection, request, EVHTTP_REQ_GET, request_url);
+
+    /**
+     * 请求发出后，立刻释放当前协程，将控制权交给协程控制器(php-fpm)
+     */
+    SG(coroutine_info).yield_coroutine_context();
+}
+
+
+void readcb(struct bufferevent* bev, void * arg)  
+{  
+    sapi_coroutine_context* context = ((coro_http_param*)arg)->context;
+    SG(coroutine_info).checkout_coroutine_context(context);
+    char* tmpStr = (char*)emalloc(sizeof(char)*4096);
+    strcpy(tmpStr,"");
+
+    char buf[1024];  
+    int n;  
+    struct evbuffer* input = bufferevent_get_input(bev);  
+    while ((n = evbuffer_remove(input, buf, sizeof(buf))) > 0)   
+    {  
+        // fwrite(buf, 1, n, stdout);  
+        strncat(tmpStr,buf,n);
+    }  
+
+
+
+    /**
+    * tmpStatus为0代表正常有结果，否则代表请求出错。返回值已被设置成错误提示
+    */
+    // char* tmpStr = (char*)context->tmpData;
+
+    /**
+    * return_value 是扩展函数执行时保存下来的返回值指针
+    */
+    zval* return_value = context->return_value;
+
+    /**
+    * 从全局变量中获取返回结果的buffer,并创建zend_string类型的结果
+    */
+    zend_string* result = zend_string_init(tmpStr,strlen(tmpStr)*sizeof(char),0);
+
+    /**
+    * 设置函数返回值
+    */
+    RETVAL_STR(result);
+    free_request(arg);
+    efree(tmpStr);
+
+    /**
+    * 继续执行当前协程的PHP脚本
+    */
+    SG(coroutine_info).resume_coroutine_context();
+
+}  
+void eventcb(struct bufferevent* bev, short events, void * arg)  
+{  
+    sapi_coroutine_context* context = ((coro_http_param*)arg)->context;
+    SG(coroutine_info).checkout_coroutine_context(context);
+
+
+    if (events & BEV_EVENT_CONNECTED)   
+    {  
+        // printf("Connect okay.\n");  
+    }   
+    else if (events & (BEV_EVENT_ERROR|BEV_EVENT_EOF))  
+    {   
+        if (events & BEV_EVENT_ERROR)   
+        {  
+            int err = bufferevent_socket_get_dns_error(bev);  
+            if (err)  
+            printf("DNS error: %s\n", evutil_gai_strerror(err));  
+        }  
+
+        bufferevent_free(bev);   
+
+        
+    }  
+}  
+
+
+PHP_FUNCTION(ce_http_get)
+{
+    /**
+     * 保存ce_http_get返回值指针到协程中，当evhttp返回时会用到
+     */
+    SG(coroutine_info).context->return_value = return_value; 
+
+    zval* param;
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &param) == FAILURE){
+        zend_string* result = zend_string_init("param error!",strlen("param error!")*sizeof(char),0);
+        RETURN_STR(result);
+    }
+    char* url = ZSTR_VAL(zval_get_string(param));
+
+    struct evhttp_uri* uri = evhttp_uri_parse(url);
+    coro_http_param* coro_param = malloc(sizeof(coro_http_param));
+    coro_param->context = SG(coroutine_info).context;
+    coro_param->uri = uri;
+
+    if (!uri)
+    {
+        zend_string* result = zend_string_init("uri create error!",strlen("uri create error!")*sizeof(char),0);
+        RETURN_STR(result);
+    }
+
+    const char* host = evhttp_uri_get_host(uri);
+    if (!host)
+    {
+        zend_string* result = zend_string_init("host error!",strlen("host error!")*sizeof(char),0);
+        RETURN_STR(result);
+    }
+
+    int port = evhttp_uri_get_port(uri);
+    if (port < 0) port = 80;
+
+    // const char* request_url = url;
+    const char* path = evhttp_uri_get_path(uri);
+    // if (path == NULL || strlen(path) == 0)
+    // {
+    //     request_url = "/";
+    // }
+
+
+    /**
+     * 这里与正常使用不同的是，要使用协程里的event_base，并且后面不需要调用loop方法（使用系统的loop）
+     */
+    struct event_base *base = SG(coroutine_info).get_event_base();
+    struct evdns_base *dnsbase = SG(coroutine_info).get_evdns_base(); 
+    struct bufferevent* bev;
+
+
+    bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);  
+    bufferevent_setcb(bev, readcb, NULL, eventcb, coro_param);  
+    bufferevent_enable(bev, EV_READ|EV_WRITE);  
+    evbuffer_add_printf(bufferevent_get_output(bev), "GET %s\r\n", path);  
+    bufferevent_socket_connect_hostname(bev, dnsbase, AF_UNSPEC, host, port);  
+
+    /**
+     * 请求发出后，立刻释放当前协程，将控制权交给协程控制器(php-fpm)
+     */
+    SG(coroutine_info).yield_coroutine_context();
+}
+
+
+PHP_FUNCTION(ce_context_index)
+{
+  RETURN_LONG(SG(coroutine_info).context->thread_id);
+}
+
+PHP_FUNCTION(ce_context_fd)
+{
+  RETURN_LONG(SG(coroutine_info).context->fd);
+}
+
+/* }}} */
+/* The previous line is meant for vim and emacs, so it can correctly fold and
+   unfold functions in source code. See the corresponding marks just before
+   function definition, where the functions purpose is also documented. Please
+   follow this convention for the convenience of others editing your code.
+*/
+
+
+/* {{{ php_coro_http_init_globals
+ */
+/* Uncomment this function if you have INI entries
+static void php_coro_http_init_globals(zend_coro_http_globals *coro_http_globals)
+{
+	coro_http_globals->global_value = 0;
+	coro_http_globals->global_string = NULL;
+}
+*/
+/* }}} */
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(coro_http)
+{
+	/* If you have INI entries, uncomment these lines
+	REGISTER_INI_ENTRIES();
+	*/
+	return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(coro_http)
+{
+	/* uncomment this line if you have INI entries
+	UNREGISTER_INI_ENTRIES();
+	*/
+	return SUCCESS;
+}
+/* }}} */
+
+/* Remove if there's nothing to do at request start */
+/* {{{ PHP_RINIT_FUNCTION
+ */
+PHP_RINIT_FUNCTION(coro_http)
+{
+#if defined(COMPILE_DL_CORO_HTTP) && defined(ZTS)
+	ZEND_TSRMLS_CACHE_UPDATE();
+#endif
+	return SUCCESS;
+}
+/* }}} */
+
+/* Remove if there's nothing to do at request end */
+/* {{{ PHP_RSHUTDOWN_FUNCTION
+ */
+PHP_RSHUTDOWN_FUNCTION(coro_http)
+{
+	return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(coro_http)
+{
+	php_info_print_table_start();
+	php_info_print_table_header(2, "coro_http support", "enabled");
+	php_info_print_table_end();
+
+	/* Remove comments if you have entries in php.ini
+	DISPLAY_INI_ENTRIES();
+	*/
+}
+/* }}} */
+
+/* {{{ coro_http_functions[]
+ *
+ * Every user visible function must have an entry in coro_http_functions[].
+ */
+const zend_function_entry coro_http_functions[] = {
+	PHP_FE(coro_http_get,	NULL)	
+    PHP_FE(ce_http_get, NULL) 
+    PHP_FE(ce_context_index, NULL) 
+    PHP_FE(ce_context_fd, NULL) 
+	PHP_FE_END	/* Must be the last line in coro_http_functions[] */
+};
+/* }}} */
+
+/* {{{ coro_http_module_entry
+ */
+zend_module_entry coro_http_module_entry = {
+	STANDARD_MODULE_HEADER,
+	"coro_http",
+	coro_http_functions,
+	PHP_MINIT(coro_http),
+	PHP_MSHUTDOWN(coro_http),
+	PHP_RINIT(coro_http),		/* Replace with NULL if there's nothing to do at request start */
+	PHP_RSHUTDOWN(coro_http),	/* Replace with NULL if there's nothing to do at request end */
+	PHP_MINFO(coro_http),
+	PHP_CORO_HTTP_VERSION,
+	STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+#ifdef COMPILE_DL_CORO_HTTP
+#ifdef ZTS
+ZEND_TSRMLS_CACHE_DEFINE()
+#endif
+ZEND_GET_MODULE(coro_http)
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/coro_http/coro_http.php b/ext/coro_http/coro_http.php
new file mode 100644
index 00000000000..d1540757ed4
--- /dev/null
+++ b/ext/coro_http/coro_http.php
@@ -0,0 +1,21 @@
+<?php
+$br = (php_sapi_name() == "cli")? "":"<br>";
+
+if(!extension_loaded('coro_http')) {
+	dl('coro_http.' . PHP_SHLIB_SUFFIX);
+}
+$module = 'coro_http';
+$functions = get_extension_funcs($module);
+echo "Functions available in the test extension:$br\n";
+foreach($functions as $func) {
+    echo $func."$br\n";
+}
+echo "$br\n";
+$function = 'confirm_' . $module . '_compiled';
+if (extension_loaded($module)) {
+	$str = $function($module);
+} else {
+	$str = "Module $module is not compiled into PHP";
+}
+echo "$str\n";
+?>
diff --git a/ext/coro_http/maketest.sh b/ext/coro_http/maketest.sh
new file mode 100644
index 00000000000..3e8813a09fc
--- /dev/null
+++ b/ext/coro_http/maketest.sh
@@ -0,0 +1,8 @@
+#########################################################################
+# File Name: maketest.sh
+# Author: ma6174
+# mail: ma6174@163.com
+# Created Time: 二  7/ 3 16:51:03 2018
+#########################################################################
+#!/bin/bash
+/usr/local/php7/bin/phpize && ./configure --with-php-config=/usr/local/php7/bin/php-config --enable-coro_http && make &&sudo  make install
diff --git a/ext/coro_http/php_coro_http.h b/ext/coro_http/php_coro_http.h
new file mode 100644
index 00000000000..4562fed61ed
--- /dev/null
+++ b/ext/coro_http/php_coro_http.h
@@ -0,0 +1,71 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 7                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2018 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Author:                                                              |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef PHP_CORO_HTTP_H
+#define PHP_CORO_HTTP_H
+
+extern zend_module_entry coro_http_module_entry;
+#define phpext_coro_http_ptr &coro_http_module_entry
+
+#define PHP_CORO_HTTP_VERSION "0.1.0" /* Replace with version number for your extension */
+
+#ifdef PHP_WIN32
+#	define PHP_CORO_HTTP_API __declspec(dllexport)
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#	define PHP_CORO_HTTP_API __attribute__ ((visibility("default")))
+#else
+#	define PHP_CORO_HTTP_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+/*
+  	Declare any global variables you may need between the BEGIN
+	and END macros here:
+
+ZEND_BEGIN_MODULE_GLOBALS(coro_http)
+	zend_long  global_value;
+	char *global_string;
+ZEND_END_MODULE_GLOBALS(coro_http)
+*/
+
+/* Always refer to the globals in your function as CORO_HTTP_G(variable).
+   You are encouraged to rename these macros something shorter, see
+   examples in any other php module directory.
+*/
+#define CORO_HTTP_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(coro_http, v)
+
+#if defined(ZTS) && defined(COMPILE_DL_CORO_HTTP)
+ZEND_TSRMLS_CACHE_EXTERN()
+#endif
+
+#endif	/* PHP_CORO_HTTP_H */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/coro_http/tests/001.phpt b/ext/coro_http/tests/001.phpt
new file mode 100644
index 00000000000..e085fecf8f7
--- /dev/null
+++ b/ext/coro_http/tests/001.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Check for coro_http presence
+--SKIPIF--
+<?php if (!extension_loaded("coro_http")) print "skip"; ?>
+--FILE--
+<?php 
+echo "coro_http extension is available";
+/*
+	you can add regression tests for your extension here
+
+  the output of your test code has to be equal to the
+  text in the --EXPECT-- section below for the tests
+  to pass, differences between the output and the
+  expected text are interpreted as failure
+
+	see php7/README.TESTING for further information on
+  writing regression tests
+*/
+?>
+--EXPECT--
+coro_http extension is available
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index d983d4c0567..3e7fbd7e366 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -2526,6 +2526,10 @@ static inline int accel_find_sapi(void)
 
 static int zend_accel_init_shm(void)
 {
+	if(accel_shared_globals){
+		return SUCCESS;
+	}
+
 	int i;
 
 	zend_shared_alloc_lock();
diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c
index 8308f008810..d26693505be 100644
--- a/ext/opcache/zend_shared_alloc.c
+++ b/ext/opcache/zend_shared_alloc.c
@@ -47,7 +47,7 @@
 static const zend_shared_memory_handlers *g_shared_alloc_handler = NULL;
 static const char *g_shared_model;
 /* pointer to globals allocated in SHM and shared across processes */
-zend_smm_shared_globals *smm_shared_globals;
+zend_smm_shared_globals *smm_shared_globals = NULL;
 
 #ifndef ZEND_WIN32
 #ifdef ZTS
@@ -148,6 +148,10 @@ static int zend_shared_alloc_try(const zend_shared_memory_handler_entry *he, siz
 
 int zend_shared_alloc_startup(size_t requested_size)
 {
+	if(smm_shared_globals){
+		return ALLOC_SUCCESS;
+	}
+
 	zend_shared_segment **tmp_shared_segments;
 	size_t shared_segments_array_size;
 	zend_smm_shared_globals tmp_shared_globals, *p_tmp_shared_globals;
diff --git a/ext/standard/config.m4 b/ext/standard/config.m4
index 61eefdc339f..9294c94a7d1 100644
--- a/ext/standard/config.m4
+++ b/ext/standard/config.m4
@@ -561,7 +561,7 @@ PHP_NEW_EXTENSION(standard, array.c base64.c basic_functions.c browscap.c crc32.
                             http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
                             var_unserializer.c ftok.c sha1.c user_filters.c uuencode.c \
                             filters.c proc_open.c streamsfuncs.c http.c password.c \
-                            random.c,,,
+                            random.c fpm_coroutine.c,,,
 			    -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
 
 PHP_ADD_MAKEFILE_FRAGMENT
diff --git a/ext/standard/fpm_coroutine.c b/ext/standard/fpm_coroutine.c
new file mode 100644
index 00000000000..0482c0b6dca
--- /dev/null
+++ b/ext/standard/fpm_coroutine.c
@@ -0,0 +1,295 @@
+#include "php.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifdef HAVE_TIMES
+#include <sys/times.h>
+#endif
+
+#include <event2/event.h>
+#include "event2/dns.h"
+/* For sockaddr_in */  
+#include <netinet/in.h>
+#include "SAPI.h"
+#include "fpm_coroutine.h"
+#include "fastcgi.h"
+
+/* use to stor coroutine context */
+
+
+sapi_coroutine_context* global_coroutine_context_pool = NULL;
+sapi_coroutine_context* global_coroutine_context_pool_end = NULL;
+sapi_coroutine_context* global_coroutine_context_use = NULL;
+int context_count;
+struct event_base *base;
+struct evdns_base *dnsbase;
+struct event *listener_event;
+int listener_event_stop = 0;
+
+/**
+ * 测试输出LOG
+ */
+void test_log(char *text){
+
+    FILE *pfile;
+    size_t result;
+    pfile=fopen("/tmp/fpmlog.txt","a+");
+
+    int lsize=strlen(text);//获取文件长度
+
+    result=fwrite(text,sizeof(char),lsize,pfile);//将pfile中内容读入pread指向内存中
+    fclose(pfile);
+}
+
+void asser_event_stop(void){
+    if(!listener_event_stop && context_count<1){
+        listener_event_stop = 1;
+        event_del(listener_event);
+    }
+}
+
+void asser_event_continue(void){
+    if(listener_event_stop && context_count>0){
+        listener_event_stop = 0;
+        event_add(listener_event,NULL);
+    }
+}
+
+struct event_base* get_event_base(){
+    return base;
+}
+
+struct evdns_base* get_evdns_base(){
+    return dnsbase;
+}
+
+/**
+ * 注册libevent
+ */
+int regist_event(int fcgi_fd,void (*do_accept())){
+    
+    base = event_base_new();//初始化libevent
+    if (!base)  
+        return 0; //libevent 初始化失败 
+    dnsbase = evdns_base_new(base, 1);
+    if (!dnsbase)
+        return 0;
+
+    listener_event = event_new(base, fcgi_fd, EV_READ|EV_PERSIST, do_accept, base);
+    evutil_make_socket_nonblocking(fcgi_fd);
+
+    /* 添加事件 */  
+    event_add(listener_event, NULL);
+    event_base_dispatch(base);
+
+    return 1;
+}
+
+void checkout_coroutine_context(sapi_coroutine_context* context){
+    set_force_thread_id(context->thread_id);
+    tsrm_set_interpreter_context(get_tsrm_tls_entry(context->thread_id));
+}
+
+void resume_coroutine_context(){
+
+    sapi_coroutine_context* context = SG(coroutine_info).context;
+    if(context->fd == NULL){//客户端已断开连接
+        free_coroutine_context(SG(coroutine_info).context);
+        return;
+    }
+
+    int r = setjmp(*context->buf_ptr);//yield之后的代码段，设置起始标记
+    if(r == CORO_DEFAULT){//继续
+        // zend_vm_stack_free_args(context->prev_execute_data);
+        // zend_vm_stack_free_call_frame(context->prev_execute_data);
+
+        SG(coroutine_info).init_request((void *)context->request);//=====tmp
+        SG(coroutine_info).fpm_request_executing();
+        EG(current_execute_data) = context->prev_execute_data;
+
+        EG(current_execute_data)->opline++;
+
+        zend_execute_ex(EG(current_execute_data));
+        // zend_vm_stack_free_call_frame(EG(current_execute_data));
+
+        zend_exception_restore();
+        zend_try_exception_handler();
+        if (EG(exception)) {
+            zend_exception_error(EG(exception), E_ERROR);
+        }
+        destroy_op_array(context->op_array);
+        efree_size(context->op_array, sizeof(zend_op_array));
+
+        //from php_execute_script_coro ,处理异常
+        if (EG(exception)) {
+            zend_try {
+                zend_exception_error(EG(exception), E_ERROR);
+            } zend_end_try();
+        }
+
+#if HAVE_BROKEN_GETCWD
+        if ((int)*context->old_cwd_fd != -1) {
+            fchdir(*context->old_cwd_fd);
+            close(*context->old_cwd_fd);
+        }
+#else
+        SG(coroutine_info).free_old_cwd(context->old_cwd,context->use_heap);
+#endif
+        
+        SG(coroutine_info).close_request();
+        free_coroutine_context(SG(coroutine_info).context);
+
+    }else{
+
+    }
+}
+
+void yield_coroutine_context(){
+
+    sapi_coroutine_context* context = SG(coroutine_info).context;
+
+    context->prev_execute_data = EG(current_execute_data)->prev_execute_data;
+
+    longjmp(*context->buf_ptr,CORO_YIELD);
+}
+
+void free_coroutine_context(sapi_coroutine_context* context){
+    //先清理关系
+    if(context->prev && context->next){
+        context->prev->next = context->next;
+        context->next->prev = context->prev;
+        context->prev = NULL;
+        context->next = NULL;
+    }else if(context->prev){//最后一个
+        context->prev->next = NULL;
+        context->prev = NULL;
+    }else if(context->next){//第一个
+        global_coroutine_context_use = context->next;
+        context->next->prev = NULL;
+        context->next = NULL;
+    }else{
+        global_coroutine_context_use = NULL;
+    }
+
+    //加入新关系,末尾添加
+    if(global_coroutine_context_pool_end == NULL){//可用池为空
+        //可用池为空
+        global_coroutine_context_pool_end = global_coroutine_context_pool = context;
+        context->prev = NULL;
+        context->next = NULL;
+    }else if(global_coroutine_context_pool_end == global_coroutine_context_pool){//可用池为1
+        global_coroutine_context_pool_end = context;
+        global_coroutine_context_pool->next = context;
+        global_coroutine_context_pool_end->prev = global_coroutine_context_pool;
+    }else{
+        context->prev = global_coroutine_context_pool_end;
+        global_coroutine_context_pool_end->next = context;
+        context->next = NULL;
+        global_coroutine_context_pool_end = context;
+    }
+
+    context_count++;
+    if(context->fd != NULL)
+        bufferevent_free(context->bev);
+
+    asser_event_continue();
+}
+
+void init_coroutine_set_request(sapi_coroutine_context* context,fcgi_request *request){
+    context->request = request;
+    SG(coroutine_info).context = context;
+}
+
+/**
+ * 切换协程,取池中第一个
+ */
+sapi_coroutine_context* use_coroutine_context(){
+    if(context_count>0){
+        sapi_coroutine_context* result = global_coroutine_context_pool;
+
+        if(global_coroutine_context_pool && global_coroutine_context_pool->next){
+            //有两个以上
+            global_coroutine_context_pool = global_coroutine_context_pool->next;
+            global_coroutine_context_pool->prev = NULL;
+        }else{
+            //有一个
+            global_coroutine_context_pool = NULL;
+            global_coroutine_context_pool_end =NULL;
+        }
+
+        //加入使用池
+        if(global_coroutine_context_use){
+            result->next = global_coroutine_context_use;
+            result->prev = NULL;
+            global_coroutine_context_use->prev = result;
+            global_coroutine_context_use = result;
+        }else{
+            global_coroutine_context_use = result;
+            global_coroutine_context_use->next = NULL;
+            global_coroutine_context_use->prev = NULL;
+        }
+
+        context_count--;
+
+        set_force_thread_id(result->thread_id);
+        tsrm_set_interpreter_context(get_tsrm_tls_entry(result->thread_id));
+
+        asser_event_stop();
+        return result;
+    }else{
+        asser_event_stop();
+        return NULL;
+    }
+}
+
+
+/**
+ * 初始化上下文
+ */
+void init_coroutine_context(int idx){
+    //初始化context 上下文
+    sapi_coroutine_context *context = malloc(sizeof(sapi_coroutine_context));
+    context->request = NULL;
+    context->buf_ptr = malloc(sizeof(jmp_buf));
+    context->req_ptr = malloc(sizeof(jmp_buf));
+    context->thread_id = idx;
+    context->next = NULL;
+    context->prev = NULL;
+
+    //context加入链表
+    if(global_coroutine_context_pool == NULL){
+        global_coroutine_context_pool_end = global_coroutine_context_pool = context;
+    }else if(global_coroutine_context_pool_end == global_coroutine_context_pool){//池中有一个数据
+        global_coroutine_context_pool = context;
+        global_coroutine_context_pool->next = global_coroutine_context_pool_end;
+        global_coroutine_context_pool_end->prev = global_coroutine_context_pool;
+    }else{
+        global_coroutine_context_pool->prev = context;
+        context->next = global_coroutine_context_pool;
+        global_coroutine_context_pool = context;
+    }
+    context_count++;
+}
+
+void init_coroutine_static(){
+    global_coroutine_context_pool = NULL;
+    global_coroutine_context_pool_end = NULL;
+    global_coroutine_context_use = NULL;
+    context_count = 0;
+}
+
+void init_coroutine_info(){
+    SG(coroutine_info).context_count = &context_count;
+    SG(coroutine_info).context = NULL;
+    SG(coroutine_info).test_log = test_log;
+    SG(coroutine_info).yield_coroutine_context = yield_coroutine_context;
+    SG(coroutine_info).checkout_coroutine_context = checkout_coroutine_context;
+    SG(coroutine_info).resume_coroutine_context = resume_coroutine_context;
+    SG(coroutine_info).get_event_base = get_event_base;
+    SG(coroutine_info).get_evdns_base = get_evdns_base;
+
+    SG(coroutine_info).context_pool = &global_coroutine_context_pool;
+    SG(coroutine_info).context_use = &global_coroutine_context_use;
+
+}
\ No newline at end of file
diff --git a/ext/standard/fpm_coroutine.h b/ext/standard/fpm_coroutine.h
new file mode 100644
index 00000000000..f7df0cae31e
--- /dev/null
+++ b/ext/standard/fpm_coroutine.h
@@ -0,0 +1,29 @@
+#ifndef FPM_COROUTINE_H
+#define FPM_COROUTINE_H 1
+
+#include <event2/event.h>
+/* For sockaddr_in */  
+#include <netinet/in.h>
+
+#include "fastcgi.h"
+#include "SAPI.h"
+
+void test_log(char *text);
+
+int regist_event(int fcgi_fd,void (*do_accept()));
+
+void checkout_coroutine_context(sapi_coroutine_context* context);
+void resume_coroutine_context();
+void yield_coroutine_context();
+void free_coroutine_context(sapi_coroutine_context* context);
+
+void init_coroutine_context(int idx);
+sapi_coroutine_context* use_coroutine_context();
+void init_coroutine_set_request(sapi_coroutine_context* context,fcgi_request *request);
+
+
+void init_coroutine_info();
+
+void init_coroutine_static();
+
+#endif
diff --git a/main/SAPI.c b/main/SAPI.c
index 16dc971791a..50c4b691414 100644
--- a/main/SAPI.c
+++ b/main/SAPI.c
@@ -1053,6 +1053,10 @@ SAPI_API int sapi_get_fd(int *fd)
 	}
 }
 
+SAPI_API void sapi_init(){
+	sapi_module.input_filter_init = NULL;
+}
+
 SAPI_API int sapi_force_http_10(void)
 {
 	if (sapi_module.force_http_10) {
diff --git a/main/SAPI.h b/main/SAPI.h
index 0f686502b28..835d66652d2 100644
--- a/main/SAPI.h
+++ b/main/SAPI.h
@@ -31,6 +31,9 @@
 #include "win32/php_stdint.h"
 #endif
 #include <sys/stat.h>
+#include "fastcgi.h"
+
+
 
 #define SAPI_OPTION_NO_CHDIR 1
 #define SAPI_POST_BLOCK_SIZE 0x4000
@@ -116,6 +119,57 @@ typedef struct {
 	int proto_num;
 } sapi_request_info;
 
+#define CORO_DEFAULT 0
+#define CORO_YIELD 1
+#define CORO_END 2
+#define CORO_RESUME 3
+#define CORO_START 4
+
+typedef struct _sapi_coroutine_context{
+    jmp_buf *buf_ptr;
+    jmp_buf *req_ptr;
+    zend_op_array *op_array;
+    zend_execute_data *prev_execute_data;//execute for execute before yield
+    struct _sapi_coroutine_context *next;
+    struct _sapi_coroutine_context *prev;
+    //请求过程中用到的全局变量
+#if HAVE_BROKEN_GETCWD
+    volatile int *old_cwd_fd;
+#else
+    char *old_cwd;
+    zend_bool use_heap;
+#endif
+    fcgi_request *request;
+    sapi_request_info request_info;
+    int thread_id;
+    zval* return_value;
+    void* tmpData;//use to store data
+    int fd;//if 0 or null ,connection close
+    struct bufferevent* bev;
+} sapi_coroutine_context;
+
+/**
+ * 用于存储coroutine libevent
+ */
+typedef struct _g_sapi_coroutine_info{
+    sapi_coroutine_context* context;//全局当前context
+    int* context_count;//context池中context当前数量
+    sapi_coroutine_context** context_pool;//未使用的context池   双向不闭合链表
+    sapi_coroutine_context** context_use;//正在使用的context池   双向不闭合链表
+
+    void(*test_log)(char *text);//output test log
+    void(*checkout_coroutine_context)(sapi_coroutine_context* context);
+    void(*resume_coroutine_context)();
+    void(*yield_coroutine_context)();
+    struct event_base* (*get_event_base)();
+    struct evdns_base* (*get_evdns_base)();
+    void(*close_request)();
+    void(*fpm_request_executing)();
+    void(*init_request)(void *request);
+    void(*free_old_cwd)(char *old_cwd,zend_bool use_heap);
+    int idx;
+    int request_body_fd;
+} sapi_coroutine_info;
 
 typedef struct _sapi_globals_struct {
 	void *server_context;
@@ -135,6 +189,7 @@ typedef struct _sapi_globals_struct {
 	HashTable known_post_content_types;
 	zval callback_func;
 	zend_fcall_info_cache fci_cache;
+	sapi_coroutine_info coroutine_info;
 } sapi_globals_struct;
 
 
@@ -208,6 +263,7 @@ SAPI_API size_t sapi_apply_default_charset(char **mimetype, size_t len);
 SAPI_API void sapi_activate_headers_only(void);
 
 SAPI_API int sapi_get_fd(int *fd);
+SAPI_API void sapi_init();
 SAPI_API int sapi_force_http_10(void);
 
 SAPI_API int sapi_get_target_uid(uid_t *);
diff --git a/main/fastcgi.c b/main/fastcgi.c
index 31816618771..0f19843811e 100644
--- a/main/fastcgi.c
+++ b/main/fastcgi.c
@@ -35,6 +35,9 @@
 
 #include <windows.h>
 
+#include <event2/event.h>
+#include <event2/bufferevent.h>
+
 typedef unsigned int in_addr_t;
 
 struct sockaddr_un {
@@ -213,6 +216,7 @@ struct _fcgi_request {
 	int            listen_socket;
 	int            tcp;
 	int            fd;
+	struct bufferevent *bev;
 	int            id;
 	int            keep;
 #ifdef TCP_NODELAY
@@ -919,8 +923,16 @@ void fcgi_destroy_request(fcgi_request *req) {
 	free(req);
 }
 
+
 static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count)
 {
+	// struct evbuffer *evreturn;
+	// evreturn = evbuffer_new();
+	// evbuffer_add_printf(evreturn,buf);
+	// bufferevent_write_buffer(req->bev,evreturn);
+	// evbuffer_free(evreturn);
+	// return count;
+
 	int    ret;
 	size_t n = 0;
 
@@ -936,16 +948,20 @@ static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t coun
 			unsigned int out_len = tmp > UINT_MAX ? UINT_MAX : (unsigned int)tmp;
 
 			ret = write(req->fd, ((char*)buf)+n, out_len);
+			// ret = bufferevent_write(req->bev, ((char*)buf)+n, out_len);
 		} else {
 			int out_len = tmp > INT_MAX ? INT_MAX : (int)tmp;
 
 			ret = send(req->fd, ((char*)buf)+n, out_len, 0);
+			// ret = bufferevent_write(req->bev, ((char*)buf)+n, out_len);
 			if (ret <= 0) {
 				errno = WSAGetLastError();
 			}
 		}
 #else
 		ret = write(req->fd, ((char*)buf)+n, count-n);
+		// bufferevent_write(req->bev, ((char*)buf)+n, count-n);
+		// ret = count-n;
 #endif
 		if (ret > 0) {
 			n += ret;
@@ -958,6 +974,8 @@ static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t coun
 
 static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count)
 {
+	// int n = bufferevent_read(req->bev, ((char*)buf), count);
+	// return n;
 	int    ret;
 	size_t n = 0;
 
@@ -972,17 +990,20 @@ static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count
 		if (!req->tcp) {
 			unsigned int in_len = tmp > UINT_MAX ? UINT_MAX : (unsigned int)tmp;
 
-			ret = read(req->fd, ((char*)buf)+n, in_len);
+			// ret = read(req->fd, ((char*)buf)+n, in_len);
+			ret = bufferevent_read(req->bev, ((char*)buf)+n, in_len);
 		} else {
 			int in_len = tmp > INT_MAX ? INT_MAX : (int)tmp;
 
 			ret = recv(req->fd, ((char*)buf)+n, in_len, 0);
+			// ret = bufferevent_read(req->bev, ((char*)buf)+n, in_len);
 			if (ret <= 0) {
 				errno = WSAGetLastError();
 			}
 		}
 #else
-		ret = read(req->fd, ((char*)buf)+n, count-n);
+		// ret = read(req->fd, ((char*)buf)+n, count-n);
+		ret = bufferevent_read(req->bev, ((char*)buf)+n, count-n);
 #endif
 		if (ret > 0) {
 			n += ret;
@@ -1719,6 +1740,37 @@ void fcgi_loadenv(fcgi_request *req, fcgi_apply_func func, zval *array)
 	fcgi_hash_apply(&req->env, func, array);
 }
 
+
+//自定义，写入fd
+void fcgi_set_fd(fcgi_request *req,int fd)
+{
+    req->fd = fd;
+}
+
+//自定义，写入fd
+int fcgi_get_fd(fcgi_request *req)
+{
+    return req->fd;
+}
+
+//自定义，写入bev
+void fcgi_set_bev(fcgi_request *req,void* bev)
+{
+    req->bev = (struct bufferevent*)bev;
+}
+
+struct bufferevent *fcgi_get_bev(fcgi_request *req)
+{
+    return req->bev;
+}
+
+//自定义，初始化req回调
+void init_request_callback(fcgi_request *req){
+	req->hook.on_accept();
+    req->hook.on_read();
+    fcgi_read_request(req);
+}
+
 #ifdef _WIN32
 void fcgi_impersonate(void)
 {
diff --git a/main/fastcgi.h b/main/fastcgi.h
index 3ae3e8844f0..0371fd204c8 100644
--- a/main/fastcgi.h
+++ b/main/fastcgi.h
@@ -19,6 +19,8 @@
 /* $Id$ */
 
 /* FastCGI protocol */
+#ifndef FCGI_H
+#define FCGI_H 1
 
 #define FCGI_VERSION_1 1
 
@@ -129,6 +131,15 @@ void fcgi_impersonate(void);
 void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len);
 void fcgi_free_mgmt_var_cb(zval *zv);
 
+/**
+ * reset the fd of fcgi_request
+ */
+void fcgi_set_fd(fcgi_request *req,int fd);
+int fcgi_get_fd(fcgi_request *req);
+void fcgi_set_bev(fcgi_request *req,void* bev);
+struct bufferevent *fcgi_get_bev(fcgi_request *req);
+//自定义，初始化req回调
+void init_request_callback(fcgi_request *req);
 /*
  * Local variables:
  * tab-width: 4
@@ -137,3 +148,4 @@ void fcgi_free_mgmt_var_cb(zval *zv);
  * vim600: sw=4 ts=4 fdm=marker
  * vim<600: sw=4 ts=4
  */
+#endif
diff --git a/main/main.c b/main/main.c
index 7deb3010d9a..2a83d51ad0a 100644
--- a/main/main.c
+++ b/main/main.c
@@ -672,6 +672,19 @@ PHPAPI int php_get_module_initialized(void)
 }
 /* }}} */
 
+/* {{{ php_module_initialized
+ */
+PHPAPI void php_module_initialized()
+{
+	module_initialized = 0;
+
+	zend_module_entry *mob;
+	ZEND_HASH_FOREACH_PTR(&module_registry, mob) {
+		mob->module_started = 0;
+	} ZEND_HASH_FOREACH_END();
+}
+/* }}} */
+
 /* {{{ php_log_err_with_severity
  */
 PHPAPI ZEND_COLD void php_log_err_with_severity(char *log_message, int syslog_type_int)
@@ -2135,8 +2148,10 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
 	memset(&core_globals, 0, sizeof(core_globals));
 	php_startup_ticks();
 #endif
+
 	gc_globals_ctor();
 
+	//初始化内存池
 	zuf.error_function = php_error_cb;
 	zuf.printf_function = php_printf;
 	zuf.write_function = php_output_wrapper;
@@ -2297,8 +2312,8 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
 	   ahead of all other internals
 	 */
 	php_ini_register_extensions();
-	zend_startup_modules();
 
+	zend_startup_modules();
 	/* start Zend extensions */
 	zend_startup_extensions();
 
@@ -2391,7 +2406,6 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
 
 	sapi_deactivate();
 	module_startup = 0;
-
 	shutdown_memory_manager(1, 0);
 	zend_interned_strings_snapshot();
  	virtual_cwd_activate();
diff --git a/main/output.c b/main/output.c
index 577266d25a3..450e9f07216 100644
--- a/main/output.c
+++ b/main/output.c
@@ -161,7 +161,7 @@ PHPAPI void php_output_shutdown(void)
 PHPAPI int php_output_activate(void)
 {
 #ifdef ZTS
-	memset((*((void ***) ZEND_TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(output_globals_id)], 0, sizeof(zend_output_globals));
+	memset((*((void ***) tsrm_get_ls_cache()))[TSRM_UNSHUFFLE_RSRC_ID(output_globals_id)], 0, sizeof(zend_output_globals));
 #else
 	memset(&output_globals, 0, sizeof(zend_output_globals));
 #endif
diff --git a/main/php.h b/main/php.h
index 62312de84ec..c3b016f3a87 100644
--- a/main/php.h
+++ b/main/php.h
@@ -291,6 +291,7 @@ PHPAPI size_t php_write(void *buf, size_t size);
 PHPAPI size_t php_printf(const char *format, ...) PHP_ATTRIBUTE_FORMAT(printf, 1,
 		2);
 PHPAPI int php_get_module_initialized(void);
+PHPAPI void php_module_initialized();
 #ifdef HAVE_SYSLOG_H
 #include "php_syslog.h"
 #define php_log_err(msg) php_log_err_with_severity(msg, LOG_NOTICE)
diff --git a/sapi/cgi/config9.m4 b/sapi/cgi/config.m4
similarity index 87%
rename from sapi/cgi/config9.m4
rename to sapi/cgi/config.m4
index 1935864be37..c9cc2c17cbf 100644
--- a/sapi/cgi/config9.m4
+++ b/sapi/cgi/config.m4
@@ -55,16 +55,16 @@ if test "$PHP_CGI" != "no"; then
     case $host_alias in
       *aix*)
         if test "$php_sapi_module" = "shared"; then
-          BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/.libs\/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+          BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/.libs\/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -levent -o \$(SAPI_CGI_PATH)"
         else
-          BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+          BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -levent -o \$(SAPI_CGI_PATH)"
         fi
         ;;
       *darwin*)
-        BUILD_CGI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_FASTCGI_OBJS:.lo=.o) \$(PHP_CGI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+        BUILD_CGI="\$(CC)  \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_FASTCGI_OBJS:.lo=.o) \$(PHP_CGI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -levent -o \$(SAPI_CGI_PATH)"
       ;;
       *)
-        BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+        BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -levent -o \$(SAPI_CGI_PATH)"
       ;;
     esac
 
diff --git a/sapi/cli/config.m4 b/sapi/cli/config.m4
index 04db2fecee7..0b41e79e939 100644
--- a/sapi/cli/config.m4
+++ b/sapi/cli/config.m4
@@ -42,13 +42,13 @@ if test "$PHP_CLI" != "no"; then
     fi
     ;;
   *darwin*)
-    BUILD_CLI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_CLI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)"
+    BUILD_CLI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_CLI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -levent -o \$(SAPI_CLI_PATH)"
     ;;
   *netware*)
-    BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_BINARY_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -Lnetware -lphp7lib -o \$(SAPI_CLI_PATH)"
+    BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_BINARY_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -Lnetware -lphp7lib -levent -o \$(SAPI_CLI_PATH)"
     ;;
   *)
-    BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)"
+    BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -levent -o \$(SAPI_CLI_PATH)"
     ;;
   esac
 
diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4
index e6a1a498573..a9148bfe1ce 100644
--- a/sapi/fpm/config.m4
+++ b/sapi/fpm/config.m4
@@ -712,13 +712,13 @@ if test "$PHP_FPM" != "no"; then
 
   case $host_alias in
       *aix*)
-        BUILD_FPM="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FPM_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
+        BUILD_FPM="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FPM_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -levent -o \$(SAPI_FPM_PATH)"
         ;;
       *darwin*)
-        BUILD_FPM="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_FASTCGI_OBJS:.lo=.o) \$(PHP_FPM_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
+        BUILD_FPM="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_FASTCGI_OBJS:.lo=.o) \$(PHP_FPM_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -levent -o \$(SAPI_FPM_PATH)"
       ;;
       *)
-        BUILD_FPM="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
+        BUILD_FPM="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -levent -o \$(SAPI_FPM_PATH)"
       ;;
   esac
 
diff --git a/sapi/fpm/fpm/fpm.c b/sapi/fpm/fpm/fpm.c
index e43eb5a86d6..641299ea8c7 100644
--- a/sapi/fpm/fpm/fpm.c
+++ b/sapi/fpm/fpm/fpm.c
@@ -93,7 +93,7 @@ int fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int t
 int fpm_run(int *max_requests) /* {{{ */
 {
 	struct fpm_worker_pool_s *wp;
-
+	// goto run_child;
 	/* create initial children in all pools */
 	for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
 		int is_parent;
diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c
index 24a7e5d56ac..8f9147cfe8d 100644
--- a/sapi/fpm/fpm/fpm_main.c
+++ b/sapi/fpm/fpm/fpm_main.c
@@ -22,7 +22,6 @@
 */
 
 /* $Id: cgi_main.c 291497 2009-11-30 14:43:22Z dmitry $ */
-
 #include "php.h"
 #include "php_globals.h"
 #include "php_variables.h"
@@ -109,6 +108,21 @@ int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS;
 #include "fpm_log.h"
 #include "zlog.h"
 
+#include <event2/event.h>
+#include <event2/bufferevent.h>
+
+
+// coroutine begin ====
+#include "ext/standard/fpm_coroutine.h"
+#define COROUTINE_INIT_START \
+	for(coroutine_index=0;coroutine_index<coroutine_count;coroutine_index++){\
+        set_force_thread_id(coroutine_index);\
+        tsrm_set_interpreter_context(get_tsrm_tls_entry(coroutine_index));\
+
+#define COROUTINE_INIT_END };\
+        set_force_thread_id(0);\
+        tsrm_set_interpreter_context(main_context);\
+
 #ifndef PHP_WIN32
 /* XXX this will need to change later when threaded fastcgi is implemented.  shane */
 struct sigaction act, old_term, old_quit, old_int;
@@ -125,9 +139,13 @@ static void (*php_php_import_environment_variables)(zval *array_ptr);
 static int parent = 1;
 #endif
 
-static int request_body_fd;
+// static int request_body_fd;
 static int fpm_is_running = 0;
 
+
+static int max_requests = 500;
+static int requests = 0;
+
 static char *sapi_cgibin_getenv(char *name, size_t name_len);
 static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg);
 
@@ -482,13 +500,16 @@ static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes) /* {{{ */
 	}
 	while (read_bytes < count_bytes) {
 		fcgi_request *request = (fcgi_request*) SG(server_context);
-		if (request_body_fd == -1) {
+		// if (request_body_fd == -1) {
+		if (SG(coroutine_info).request_body_fd == -1) {
 			char *request_body_filename = FCGI_GETENV(request, "REQUEST_BODY_FILE");
 
 			if (request_body_filename && *request_body_filename) {
-				request_body_fd = open(request_body_filename, O_RDONLY);
+				// request_body_fd = open(request_body_filename, O_RDONLY);
+				SG(coroutine_info).request_body_fd = open(request_body_filename, O_RDONLY);
 
-				if (0 > request_body_fd) {
+				// if (0 > request_body_fd) {
+				if (0 > SG(coroutine_info).request_body_fd) {
 					php_error(E_WARNING, "REQUEST_BODY_FILE: open('%s') failed: %s (%d)",
 							request_body_filename, strerror(errno), errno);
 					return 0;
@@ -497,10 +518,12 @@ static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes) /* {{{ */
 		}
 
 		/* If REQUEST_BODY_FILE variable not available - read post body from fastcgi stream */
-		if (request_body_fd < 0) {
+		// if (request_body_fd < 0) {
+		if (SG(coroutine_info).request_body_fd < 0) {
 			tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
 		} else {
-			tmp_read_bytes = read(request_body_fd, buffer + read_bytes, count_bytes - read_bytes);
+			// tmp_read_bytes = read(request_body_fd, buffer + read_bytes, count_bytes - read_bytes);
+			tmp_read_bytes = read(SG(coroutine_info).request_body_fd, buffer + read_bytes, count_bytes - read_bytes);
 		}
 		if (tmp_read_bytes <= 0) {
 			break;
@@ -1565,6 +1588,453 @@ static zend_module_entry cgi_module_entry = {
 	STANDARD_MODULE_PROPERTIES
 };
 
+//这里是执行代码的最终函数
+ZEND_API void zend_execute_coro(zend_op_array *op_array, zval *return_value)
+{
+	sapi_coroutine_context* context = SG(coroutine_info).context;
+	// context->ret = return_value;
+	context->op_array = op_array;
+
+	zend_execute_data *execute_data;
+
+	if (EG(exception) != NULL) {
+		return;
+	}
+
+	execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
+		(zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data)));
+	if (EG(current_execute_data)) {
+		execute_data->symbol_table = zend_rebuild_symbol_table();
+	} else {
+		execute_data->symbol_table = &EG(symbol_table);
+	}
+
+	// EX(prev_execute_data) = EG(current_execute_data);
+	// i_init_execute_data(execute_data, op_array, return_value);
+	zend_init_execute_data(execute_data, op_array, return_value);
+
+	int r = setjmp(*context->buf_ptr);
+    if(r == CORO_DEFAULT){//first run
+		zend_execute_ex(execute_data);
+		zend_vm_stack_free_call_frame(execute_data);
+	}else{
+        longjmp(*context->req_ptr,CORO_YIELD);
+    }
+}
+
+ZEND_API int zend_execute_scripts_coro(int type, zval *retval, int file_count, ...) /* {{{ */
+{
+    va_list files;
+    int i;
+    zend_file_handle *file_handle;
+    zend_op_array *op_array;
+
+    va_start(files, file_count);
+    for (i = 0; i < file_count; i++) {
+        file_handle = va_arg(files, zend_file_handle *);
+        if (!file_handle) {
+            continue;
+        }
+
+        op_array = zend_compile_file(file_handle, type);
+        if (file_handle->opened_path) {
+            zend_hash_add_empty_element(&EG(included_files), file_handle->opened_path);
+        }
+        zend_destroy_file_handle(file_handle);
+        if (op_array) {
+
+            zend_execute_coro(op_array, retval);
+
+            zend_exception_restore();
+            zend_try_exception_handler();
+            if (EG(exception)) {
+                zend_exception_error(EG(exception), E_ERROR);
+            }
+
+            destroy_op_array(op_array);
+            efree_size(op_array, sizeof(zend_op_array));
+        } else if (type==ZEND_REQUIRE) {
+            va_end(files);
+            return FAILURE;
+        }
+    }
+    va_end(files);
+
+    return SUCCESS;
+}
+/* }}} */
+
+
+#if HAVE_BROKEN_GETCWD
+
+#else
+void free_old_cwd(char *old_cwd,zend_bool use_heap){
+    if (old_cwd[0] != '\0') {
+        php_ignore_value(VCWD_CHDIR(old_cwd));
+    }
+    free_alloca(old_cwd, use_heap);
+}
+#endif
+
+/* {{{ php_execute_script
+ */
+PHPAPI int php_execute_script_coro(zend_file_handle *primary_file)
+{
+    sapi_coroutine_context* context = SG(coroutine_info).context;
+    zend_file_handle *prepend_file_p, *append_file_p;
+    zend_file_handle prepend_file = {{0}, NULL, NULL, 0, 0}, append_file = {{0}, NULL, NULL, 0, 0};
+#if HAVE_BROKEN_GETCWD
+    volatile int old_cwd_fd = -1;
+    context->old_cwd_fd=&old_cwd_fd;
+#else
+    // char *old_cwd;
+    // ALLOCA_FLAG(use_heap)
+#endif
+    int retval = 0;
+
+    EG(exit_status) = 0;
+#ifndef HAVE_BROKEN_GETCWD
+# define OLD_CWD_SIZE 4096
+    context->old_cwd = do_alloca(OLD_CWD_SIZE, context->use_heap);
+    context->old_cwd[0] = '\0';
+    SG(coroutine_info).free_old_cwd = free_old_cwd;
+#endif
+
+    zend_try {
+        char realfile[MAXPATHLEN];
+
+#ifdef PHP_WIN32
+        if(primary_file->filename) {
+            UpdateIniFromRegistry((char*)primary_file->filename);
+        }
+#endif
+
+        PG(during_request_startup) = 0;
+
+        if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
+#if HAVE_BROKEN_GETCWD
+            /* this looks nasty to me */
+            old_cwd_fd = open(".", 0);
+#else
+            php_ignore_value(VCWD_GETCWD(context->old_cwd, OLD_CWD_SIZE-1));
+#endif
+            VCWD_CHDIR_FILE(primary_file->filename);
+        }
+
+        /* Only lookup the real file path and add it to the included_files list if already opened
+         *   otherwise it will get opened and added to the included_files list in zend_execute_scripts
+         */
+        if (primary_file->filename &&
+            (primary_file->filename[0] != '-' || primary_file->filename[1] != 0) &&
+            primary_file->opened_path == NULL &&
+            primary_file->type != ZEND_HANDLE_FILENAME
+        ) {
+            if (expand_filepath(primary_file->filename, realfile)) {
+                primary_file->opened_path = zend_string_init(realfile, strlen(realfile), 0);
+                zend_hash_add_empty_element(&EG(included_files), primary_file->opened_path);
+            }
+        }
+
+        if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
+            prepend_file.filename = PG(auto_prepend_file);
+            prepend_file.opened_path = NULL;
+            prepend_file.free_filename = 0;
+            prepend_file.type = ZEND_HANDLE_FILENAME;
+            prepend_file_p = &prepend_file;
+        } else {
+            prepend_file_p = NULL;
+        }
+
+        if (PG(auto_append_file) && PG(auto_append_file)[0]) {
+            append_file.filename = PG(auto_append_file);
+            append_file.opened_path = NULL;
+            append_file.free_filename = 0;
+            append_file.type = ZEND_HANDLE_FILENAME;
+            append_file_p = &append_file;
+        } else {
+            append_file_p = NULL;
+        }
+        if (PG(max_input_time) != -1) {
+#ifdef PHP_WIN32
+            zend_unset_timeout();
+#endif
+            zend_set_timeout(INI_INT("max_execution_time"), 0);
+        }
+
+
+        /*
+           If cli primary file has shabang line and there is a prepend file,
+           the `start_lineno` will be used by prepend file but not primary file,
+           save it and restore after prepend file been executed.
+         */
+        if (CG(start_lineno) && prepend_file_p) {
+
+            int orig_start_lineno = CG(start_lineno);
+
+            CG(start_lineno) = 0;
+            if (zend_execute_scripts_coro(ZEND_REQUIRE, NULL, 1, prepend_file_p) == SUCCESS) {
+                CG(start_lineno) = orig_start_lineno;
+                retval = (zend_execute_scripts_coro(ZEND_REQUIRE, NULL, 2, primary_file, append_file_p) == SUCCESS);
+            }
+        } else {
+
+            retval = (zend_execute_scripts_coro(ZEND_REQUIRE, NULL, 3, prepend_file_p, primary_file, append_file_p) == SUCCESS);
+        }
+    } zend_end_try();
+
+    if (EG(exception)) {
+        zend_try {
+            zend_exception_error(EG(exception), E_ERROR);
+        } zend_end_try();
+    }
+
+#if HAVE_BROKEN_GETCWD
+    if (old_cwd_fd != -1) {
+        fchdir(old_cwd_fd);
+        close(old_cwd_fd);
+    }
+#else
+    free_old_cwd(context->old_cwd,context->use_heap);
+    // if (old_cwd[0] != '\0') {
+    //  php_ignore_value(VCWD_CHDIR(old_cwd));
+    // }
+    // free_alloca(old_cwd, use_heap);
+#endif
+    return retval;
+}
+/* }}} */
+
+void init_request(void *request){
+    SG(server_context) = request;
+    init_request_info();//初始化request_info
+    fpm_request_info();//初始化   fpm_scoreboard_proc_s
+}
+
+void fpm_request_executing_ex(){
+    fpm_request_executing();
+}
+
+int close_request(){
+
+    // if (UNEXPECTED(request_body_fd != -1)) {
+    //     close(request_body_fd);
+    // }
+    // request_body_fd = -2;
+    if (UNEXPECTED(SG(coroutine_info).request_body_fd != -1)) {
+        close(SG(coroutine_info).request_body_fd);
+    }
+    SG(coroutine_info).request_body_fd = -2;
+    
+    if (UNEXPECTED(EG(exit_status) == 255)) {
+        if (CGIG(error_header) && *CGIG(error_header)) {
+            sapi_header_line ctr = {0};
+
+            ctr.line = CGIG(error_header);
+            ctr.line_len = strlen(CGIG(error_header));
+            sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
+        }
+    }
+
+    fpm_request_end();
+    fpm_log_write(NULL);
+
+    efree(SG(request_info).path_translated);
+    SG(request_info).path_translated = NULL;
+
+    php_request_shutdown((void *) 0);
+
+    requests++;
+    if (UNEXPECTED(max_requests && (requests == max_requests))) {
+        fcgi_request_set_keep(SG(coroutine_info).context->request, 0);
+        fcgi_finish_request(SG(coroutine_info).context->request, 0);
+        //break;
+        return 0;
+    }
+    return 1;
+    /* end of fastcgi loop */
+}
+
+typedef struct _event_param
+{
+	int fd;
+    sapi_coroutine_context* context;
+} event_param;
+
+void event_cb(struct bufferevent *bev, short event, void *arg)
+{
+	sapi_coroutine_context* context = (sapi_coroutine_context*)arg;
+    checkout_coroutine_context(context);
+	
+	// if(event & BEV_EVENT_EOF)
+	// 	test_log("connection closed\n");
+	// else if (event & BEV_EVENT_ERROR)
+	// 	test_log("some other error\n");
+
+	context->fd=NULL;//标记fd失效
+
+	//提前结束请求,但不释放context, context会在协程远程返回后释放
+
+	destroy_op_array(context->op_array);
+    efree_size(context->op_array, sizeof(zend_op_array));
+#if HAVE_BROKEN_GETCWD
+    if ((int)*context->old_cwd_fd != -1) {
+        fchdir(*context->old_cwd_fd);
+        close(*context->old_cwd_fd);
+    }
+#else
+    SG(coroutine_info).free_old_cwd(context->old_cwd,context->use_heap);
+#endif
+    SG(coroutine_info).close_request();
+
+    bufferevent_free(bev);
+
+}
+
+void socket_read_cb(struct bufferevent *bev, void *arg)
+{
+	sapi_coroutine_context* context = (sapi_coroutine_context*)arg;
+    checkout_coroutine_context(context);
+	int fd = context->fd;
+
+	evutil_make_socket_nonblocking(context->fd);
+	
+    //上下文内私有
+    zend_file_handle file_handle; 
+    fcgi_request *request = fpm_init_request(fd);//初始化request
+
+    fcgi_set_fd(request,fd);//设置libevnet fd
+
+    fcgi_set_bev(request,bev);
+
+    init_coroutine_set_request(context,request);
+    
+    //初始化回调函数（来源于）while (EXPECTED(fcgi_accept_request(request) >= 0))
+    init_request_callback(request);//初始化request回调，fpm_init_request中设置的
+
+    //------old logic
+    char *primary_script = NULL;
+	// request_body_fd = -1;
+	SG(coroutine_info).request_body_fd = -1;
+
+    SG(coroutine_info).init_request((void*)request);
+ 	// SG(server_context) = (void *) request;
+	// init_request_info();//初始化request_info
+	// fpm_request_info();//初始化   fpm_scoreboard_proc_s
+
+    // fcgi_request_set_keep(request, 1);//保持长连接
+
+	/* request startup only after we've done all we can to
+	 *            get path_translated */
+	if (UNEXPECTED(php_request_startup() == FAILURE)) {
+    //z这里要注意，设置了一些全局变量php_start_sapi  sapi_activate php_hash_environment
+		fcgi_finish_request(request, 1);
+		SG(server_context) = NULL;
+		php_module_shutdown();
+		// return FPM_EXIT_SOFTWARE;
+		return;
+	}
+
+	/* check if request_method has been sent.
+	 * if not, it's certainly not an HTTP over fcgi request */
+	if (UNEXPECTED(!SG(request_info).request_method)) {
+		goto fastcgi_request_done2;
+	}
+
+	if (UNEXPECTED(fpm_status_handle_request())) {//初始化header相关信息
+		goto fastcgi_request_done2;
+	}
+	/* If path_translated is NULL, terminate here with a 404 */
+	if (UNEXPECTED(!SG(request_info).path_translated)) {
+		zend_try {
+			zlog(ZLOG_DEBUG, "Primary script unknown");
+			SG(sapi_headers).http_response_code = 404;
+			PUTS("File not found.\n");
+		} zend_catch {
+		} zend_end_try();
+		goto fastcgi_request_done2;
+	}
+	if (UNEXPECTED(fpm_php_limit_extensions(SG(request_info).path_translated))) {
+		SG(sapi_headers).http_response_code = 403;
+		PUTS("Access denied.\n");
+		goto fastcgi_request_done2;
+	}
+
+
+	/*
+	 * have to duplicate SG(request_info).path_translated to be able to log errrors
+	 * php_fopen_primary_script seems to delete SG(request_info).path_translated on failure
+	 */
+	primary_script = estrdup(SG(request_info).path_translated);
+
+	// path_translated exists, we can continue ! 
+	if (UNEXPECTED(php_fopen_primary_script(&file_handle) == FAILURE)) {
+		zend_try {
+			zlog(ZLOG_ERROR, "Unable to open primary script: %s (%s)", primary_script, strerror(errno));
+			if (errno == EACCES) {
+				SG(sapi_headers).http_response_code = 403;
+				PUTS("Access denied.\n");
+			} else {
+				SG(sapi_headers).http_response_code = 404;
+				PUTS("No input file specified.\n");
+			}
+		} zend_catch {
+		} zend_end_try();
+		/* we want to serve more requests if this is fastcgi
+		 * so cleanup and continue, request shutdown is
+		 * handled later */
+
+		goto fastcgi_request_done2;
+	}
+
+    if (EXPECTED(primary_script)) {
+        efree(primary_script);
+    }
+
+	fpm_request_executing();//proc->request_stage  改变状态FPM_REQUEST_EXECUTING
+
+    int r = setjmp(*SG(coroutine_info).context->req_ptr);
+    if(r == CORO_DEFAULT){
+        php_execute_script_coro(&file_handle);//执行代码
+        goto fastcgi_request_done2;
+    }else if(r == CORO_YIELD){
+        return;
+    }
+
+fastcgi_request_done2:
+	
+    if(!close_request()){
+    	// return false; //todo 请求达到最大数量 结束请求
+    	event_base_loopexit(SG(coroutine_info).get_event_base(),0);
+    }
+    free_coroutine_context(SG(coroutine_info).context);
+}  
+
+void do_accept(evutil_socket_t listener, short event, void *arg)  
+{  
+	struct sockaddr_storage ss;  
+    socklen_t slen = sizeof(ss);
+    int fd = accept(listener, (struct sockaddr*)&ss, &slen);
+	evutil_make_socket_nonblocking(fd);
+
+	if(fd<0){
+		return;
+	}
+
+	sapi_coroutine_context* context = use_coroutine_context();
+    SG(coroutine_info).context = context;
+    SG(sapi_started) = 0;
+    struct event_base *base = arg;  
+
+    context->fd = fd;
+
+	struct bufferevent* bev = bufferevent_socket_new(base, context->fd, BEV_OPT_CLOSE_ON_FREE);
+	context->bev = bev;
+	bufferevent_setcb(bev, socket_read_cb, NULL, event_cb, context);
+
+	bufferevent_enable(bev, EV_READ | EV_WRITE | EV_PERSIST);
+
+}
+
 /* {{{ main
  */
 int main(int argc, char *argv[])
@@ -1583,10 +2053,8 @@ int main(int argc, char *argv[])
 	void ***tsrm_ls;
 #endif
 
-	int max_requests = 500;
-	int requests = 0;
 	int fcgi_fd = 0;
-	fcgi_request *request;
+	// fcgi_request *request;
 	char *fpm_config = NULL;
 	char *fpm_prefix = NULL;
 	char *fpm_pid = NULL;
@@ -1607,22 +2075,56 @@ int main(int argc, char *argv[])
 #endif
 #endif
 
+int coroutine_count;
+char* engine_count = getenv("PHP_COROUTINE_ENGINE_COUNT");
+if(engine_count==NULL){
+	coroutine_count = 128;
+}else{
+	coroutine_count = atoi(engine_count);
+}
+int coroutine_index = 0;
+
 #ifdef ZTS
-	tsrm_startup(1, 1, 0, NULL);
-	tsrm_ls = ts_resource(0);
+	tsrm_startup(coroutine_count, 1, 0, NULL);
+	int _j;
+    for(_j=0;_j<coroutine_count;_j++){
+        create_tsrm_tls_entry(_j);
+    }
+    set_force_thread_id(0);
+    // tsrm_ls = ts_resource(0);
+    tsrm_set_interpreter_context(get_tsrm_tls_entry(0));
 #endif
 
+    void* main_context = get_tsrm_tls_entry(0);
+
+    init_coroutine_static();//初始化context池
+
+    //初始化全部协程
+COROUTINE_INIT_START
 	zend_signal_startup();
 
 	sapi_startup(&cgi_sapi_module);
-	cgi_sapi_module.php_ini_path_override = NULL;
-	cgi_sapi_module.php_ini_ignore_cwd = 1;
+    cgi_sapi_module.php_ini_path_override = NULL;
+    cgi_sapi_module.php_ini_ignore_cwd = 1;
+
+    SG(coroutine_info).close_request = close_request;//请求关闭的回调函数
+    SG(coroutine_info).fpm_request_executing = fpm_request_executing_ex;//请求关闭的回调函数
+    SG(coroutine_info).init_request = init_request;//请求关闭的回调函数
+    SG(coroutine_info).idx = coroutine_index;
+    init_coroutine_info();
+
+    init_coroutine_context(coroutine_index);//初始化context
+COROUTINE_INIT_END
+    
+
 
+COROUTINE_INIT_START
 #ifndef HAVE_ATTRIBUTE_WEAK
 	fcgi_set_logger(fpm_fcgi_log);
 #endif
 
 	fcgi_init();
+COROUTINE_INIT_END
 
 #ifdef PHP_WIN32
 	_fmode = _O_BINARY; /* sets default for file streams to binary */
@@ -1766,6 +2268,7 @@ int main(int argc, char *argv[])
 		}
 	}
 
+    /*print php info*/
 	if (php_information) {
 		cgi_sapi_module.phpinfo_as_text = 1;
 		cgi_sapi_module.startup(&cgi_sapi_module);
@@ -1799,6 +2302,8 @@ int main(int argc, char *argv[])
 	php_optind = orig_optind;
 	php_optarg = orig_optarg;
 
+
+COROUTINE_INIT_START
 #ifdef ZTS
 	SG(request_info).path_translated = NULL;
 #endif
@@ -1806,14 +2311,20 @@ int main(int argc, char *argv[])
 	cgi_sapi_module.additional_functions = NULL;
 	cgi_sapi_module.executable_location = argv[0];
 
-	/* startup after we get the above ini override se we get things right */
-	if (cgi_sapi_module.startup(&cgi_sapi_module) == FAILURE) {
+    php_module_initialized();
+    sapi_init();
+
+    /* startup after we get the above ini override se we get things right */
+    if (cgi_sapi_module.startup(&cgi_sapi_module) == FAILURE) {
 #ifdef ZTS
-		tsrm_shutdown();
+        tsrm_shutdown();
 #endif
-		return FPM_EXIT_SOFTWARE;
-	}
+        return FPM_EXIT_SOFTWARE;
+    }
+COROUTINE_INIT_END
 
+
+COROUTINE_INIT_START
 	if (use_extended_info) {
 		CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
 	}
@@ -1858,6 +2369,9 @@ consult the installation file that came with this distribution, or visit \n\
 		}
 	}
 
+COROUTINE_INIT_END
+    
+    //初始化fpm
 	if (0 > fpm_init(argc, argv, fpm_config ? fpm_config : CGIG(fpm_config), fpm_prefix, fpm_pid, test_conf, php_allow_to_run_as_root, force_daemon, force_stderr)) {
 
 		if (fpm_globals.send_config_pipe[1]) {
@@ -1875,6 +2389,7 @@ consult the installation file that came with this distribution, or visit \n\
 		zend_quiet_write(fpm_globals.send_config_pipe[1], &writeval, sizeof(writeval));
 		close(fpm_globals.send_config_pipe[1]);
 	}
+
 	fpm_is_running = 1;
 
 	fcgi_fd = fpm_run(&max_requests);
@@ -1888,131 +2403,153 @@ consult the installation file that came with this distribution, or visit \n\
 	php_import_environment_variables = cgi_php_import_environment_variables;
 
 	/* library is already initialized, now init our request */
-	request = fpm_init_request(fcgi_fd);
-
-	zend_first_try {
-		while (EXPECTED(fcgi_accept_request(request) >= 0)) {
-			char *primary_script = NULL;
-			request_body_fd = -1;
-			SG(server_context) = (void *) request;
-			init_request_info();
-
-			fpm_request_info();
-
-			/* request startup only after we've done all we can to
-			 *            get path_translated */
-			if (UNEXPECTED(php_request_startup() == FAILURE)) {
-				fcgi_finish_request(request, 1);
-				SG(server_context) = NULL;
-				php_module_shutdown();
-				return FPM_EXIT_SOFTWARE;
-			}
-
-			/* check if request_method has been sent.
-			 * if not, it's certainly not an HTTP over fcgi request */
-			if (UNEXPECTED(!SG(request_info).request_method)) {
-				goto fastcgi_request_done;
-			}
+	// request = fpm_init_request(fcgi_fd);
+
+    
+    //-----开始libevent
+    zend_first_try {
+        int r = regist_event(fcgi_fd,do_accept);
+
+        // fcgi_destroy_request(request);
+        fcgi_shutdown();
+
+        if (cgi_sapi_module.php_ini_path_override) {
+            free(cgi_sapi_module.php_ini_path_override);
+        }
+        if (cgi_sapi_module.ini_entries) {
+            free(cgi_sapi_module.ini_entries);
+        }
+    } zend_catch {
+        exit_status = FPM_EXIT_SOFTWARE;
+    } zend_end_try();
+    //-----结束libevent
+
+
+// 	zend_first_try {
+// 		while (EXPECTED(fcgi_accept_request(request) >= 0)) {
+
+// 			char *primary_script = NULL;
+// 			request_body_fd = -1;
+// 			SG(server_context) = (void *) request;
+// 			init_request_info();
+
+// 			fpm_request_info();
+
+// 			/* request startup only after we've done all we can to
+// 			 *            get path_translated */
+// 			if (UNEXPECTED(php_request_startup() == FAILURE)) {
+// 				fcgi_finish_request(request, 1);
+// 				SG(server_context) = NULL;
+// 				php_module_shutdown();
+// 				return FPM_EXIT_SOFTWARE;
+// 			}
+
+// 			/* check if request_method has been sent.
+// 			 * if not, it's certainly not an HTTP over fcgi request */
+// 			if (UNEXPECTED(!SG(request_info).request_method)) {
+// 				goto fastcgi_request_done;
+// 			}
+
+// 			if (UNEXPECTED(fpm_status_handle_request())) {
+// 				goto fastcgi_request_done;
+// 			}
+
+// 			/* If path_translated is NULL, terminate here with a 404 */
+// 			if (UNEXPECTED(!SG(request_info).path_translated)) {
+// 				zend_try {
+// 					zlog(ZLOG_DEBUG, "Primary script unknown");
+// 					SG(sapi_headers).http_response_code = 404;
+// 					PUTS("File not found.\n");
+// 				} zend_catch {
+// 				} zend_end_try();
+// 				goto fastcgi_request_done;
+// 			}
+
+// 			if (UNEXPECTED(fpm_php_limit_extensions(SG(request_info).path_translated))) {
+// 				SG(sapi_headers).http_response_code = 403;
+// 				PUTS("Access denied.\n");
+// 				goto fastcgi_request_done;
+// 			}
+
+// 			/*
+// 			 * have to duplicate SG(request_info).path_translated to be able to log errrors
+// 			 * php_fopen_primary_script seems to delete SG(request_info).path_translated on failure
+// 			 */
+// 			primary_script = estrdup(SG(request_info).path_translated);
+
+// 			// path_translated exists, we can continue ! 
+// 			if (UNEXPECTED(php_fopen_primary_script(&file_handle) == FAILURE)) {
+// 				zend_try {
+// 					zlog(ZLOG_ERROR, "Unable to open primary script: %s (%s)", primary_script, strerror(errno));
+// 					if (errno == EACCES) {
+// 						SG(sapi_headers).http_response_code = 403;
+// 						PUTS("Access denied.\n");
+// 					} else {
+// 						SG(sapi_headers).http_response_code = 404;
+// 						PUTS("No input file specified.\n");
+// 					}
+// 				} zend_catch {
+// 				} zend_end_try();
+// 				/* we want to serve more requests if this is fastcgi
+// 				 * so cleanup and continue, request shutdown is
+// 				 * handled later */
+
+// 				goto fastcgi_request_done;
+// 			}
+
+// 			fpm_request_executing();
+
+// 			php_execute_script(&file_handle);
+
+// fastcgi_request_done:
+// 			if (EXPECTED(primary_script)) {
+// 				efree(primary_script);
+// 			}
+
+// 			if (UNEXPECTED(request_body_fd != -1)) {
+// 				close(request_body_fd);
+// 			}
+// 			request_body_fd = -2;
+
+// 			if (UNEXPECTED(EG(exit_status) == 255)) {
+// 				if (CGIG(error_header) && *CGIG(error_header)) {
+// 					sapi_header_line ctr = {0};
+
+// 					ctr.line = CGIG(error_header);
+// 					ctr.line_len = strlen(CGIG(error_header));
+// 					sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
+// 				}
+// 			}
+
+// 			fpm_request_end();
+// 			fpm_log_write(NULL);
+
+// 			efree(SG(request_info).path_translated);
+// 			SG(request_info).path_translated = NULL;
+
+// 			php_request_shutdown((void *) 0);
+
+// 			requests++;
+// 			if (UNEXPECTED(max_requests && (requests == max_requests))) {
+// 				fcgi_request_set_keep(request, 0);
+// 				fcgi_finish_request(request, 0);
+// 				break;
+// 			}
+// 			/* end of fastcgi loop */
+// 		}
+// 		fcgi_destroy_request(request);
+// 		fcgi_shutdown();
+
+// 		if (cgi_sapi_module.php_ini_path_override) {
+// 			free(cgi_sapi_module.php_ini_path_override);
+// 		}
+// 		if (cgi_sapi_module.ini_entries) {
+// 			free(cgi_sapi_module.ini_entries);
+// 		}
+// 	} zend_catch {
+// 		exit_status = FPM_EXIT_SOFTWARE;
+// 	} zend_end_try();
 
-			if (UNEXPECTED(fpm_status_handle_request())) {
-				goto fastcgi_request_done;
-			}
-
-			/* If path_translated is NULL, terminate here with a 404 */
-			if (UNEXPECTED(!SG(request_info).path_translated)) {
-				zend_try {
-					zlog(ZLOG_DEBUG, "Primary script unknown");
-					SG(sapi_headers).http_response_code = 404;
-					PUTS("File not found.\n");
-				} zend_catch {
-				} zend_end_try();
-				goto fastcgi_request_done;
-			}
-
-			if (UNEXPECTED(fpm_php_limit_extensions(SG(request_info).path_translated))) {
-				SG(sapi_headers).http_response_code = 403;
-				PUTS("Access denied.\n");
-				goto fastcgi_request_done;
-			}
-
-			/*
-			 * have to duplicate SG(request_info).path_translated to be able to log errrors
-			 * php_fopen_primary_script seems to delete SG(request_info).path_translated on failure
-			 */
-			primary_script = estrdup(SG(request_info).path_translated);
-
-			/* path_translated exists, we can continue ! */
-			if (UNEXPECTED(php_fopen_primary_script(&file_handle) == FAILURE)) {
-				zend_try {
-					zlog(ZLOG_ERROR, "Unable to open primary script: %s (%s)", primary_script, strerror(errno));
-					if (errno == EACCES) {
-						SG(sapi_headers).http_response_code = 403;
-						PUTS("Access denied.\n");
-					} else {
-						SG(sapi_headers).http_response_code = 404;
-						PUTS("No input file specified.\n");
-					}
-				} zend_catch {
-				} zend_end_try();
-				/* we want to serve more requests if this is fastcgi
-				 * so cleanup and continue, request shutdown is
-				 * handled later */
-
-				goto fastcgi_request_done;
-			}
-
-			fpm_request_executing();
-
-			php_execute_script(&file_handle);
-
-fastcgi_request_done:
-			if (EXPECTED(primary_script)) {
-				efree(primary_script);
-			}
-
-			if (UNEXPECTED(request_body_fd != -1)) {
-				close(request_body_fd);
-			}
-			request_body_fd = -2;
-
-			if (UNEXPECTED(EG(exit_status) == 255)) {
-				if (CGIG(error_header) && *CGIG(error_header)) {
-					sapi_header_line ctr = {0};
-
-					ctr.line = CGIG(error_header);
-					ctr.line_len = strlen(CGIG(error_header));
-					sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
-				}
-			}
-
-			fpm_request_end();
-			fpm_log_write(NULL);
-
-			efree(SG(request_info).path_translated);
-			SG(request_info).path_translated = NULL;
-
-			php_request_shutdown((void *) 0);
-
-			requests++;
-			if (UNEXPECTED(max_requests && (requests == max_requests))) {
-				fcgi_request_set_keep(request, 0);
-				fcgi_finish_request(request, 0);
-				break;
-			}
-			/* end of fastcgi loop */
-		}
-		fcgi_destroy_request(request);
-		fcgi_shutdown();
-
-		if (cgi_sapi_module.php_ini_path_override) {
-			free(cgi_sapi_module.php_ini_path_override);
-		}
-		if (cgi_sapi_module.ini_entries) {
-			free(cgi_sapi_module.ini_entries);
-		}
-	} zend_catch {
-		exit_status = FPM_EXIT_SOFTWARE;
-	} zend_end_try();
 
 out:
 
diff --git a/sapi/fpm/fpm/fpm_unix.c b/sapi/fpm/fpm/fpm_unix.c
index 44f8df31115..a18c47a1eaa 100644
--- a/sapi/fpm/fpm/fpm_unix.c
+++ b/sapi/fpm/fpm/fpm_unix.c
@@ -537,7 +537,7 @@ int fpm_unix_init_main() /* {{{ */
 					} else {
 						if (readval == 1) {
 							zlog(ZLOG_DEBUG, "I received a valid acknoledge from the master process, I can exit without error");
-							fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT);
+							// fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT);//exit 没必要clean up
 							exit(FPM_EXIT_OK);
 						} else {
 							zlog(ZLOG_DEBUG, "The master process returned an error !");
diff --git a/sapi/phpdbg/config.m4 b/sapi/phpdbg/config.m4
index 9fb4e629844..a20364d1400 100644
--- a/sapi/phpdbg/config.m4
+++ b/sapi/phpdbg/config.m4
@@ -45,7 +45,7 @@ if test "$BUILD_PHPDBG" = "" && test "$PHP_PHPDBG" != "no"; then
                 \$(PHP_PHPDBG_OBJS) \
                 \$(EXTRA_LIBS) \
                 \$(PHPDBG_EXTRA_LIBS) \
-                \$(ZEND_EXTRA_LIBS) \
+                \$(ZEND_EXTRA_LIBS) -levent \
          -o \$(BUILD_BINARY)"
 
   BUILD_PHPDBG_SHARED="\$(LIBTOOL) --mode=link \
@@ -56,7 +56,7 @@ if test "$BUILD_PHPDBG" = "" && test "$PHP_PHPDBG" != "no"; then
                 \$(EXTRA_LIBS) \
                 \$(PHPDBG_EXTRA_LIBS) \
                 \$(ZEND_EXTRA_LIBS) \
-                \-DPHPDBG_SHARED \
+                \-DPHPDBG_SHARED -levent \
          -o \$(BUILD_SHARED)"
 
   PHP_SUBST(BUILD_BINARY)
diff --git a/tutorial/Dockerfile b/tutorial/Dockerfile
new file mode 100644
index 00000000000..fdcd2b41a8f
--- /dev/null
+++ b/tutorial/Dockerfile
@@ -0,0 +1,4 @@
+FROM centos:latest
+COPY ./ /data/soft/php-coroutine-engine
+RUN cd /data/soft/php-coroutine-engine && sh ./tutorial/run.sh
+CMD ["/usr/bin/supervisord"]
diff --git a/tutorial/DockerfileAlpine b/tutorial/DockerfileAlpine
new file mode 100644
index 00000000000..79ff2ae5001
--- /dev/null
+++ b/tutorial/DockerfileAlpine
@@ -0,0 +1,4 @@
+FROM alpine:3.8
+COPY ./ /data/soft/php-coroutine-engine
+RUN cd /data/soft/php-coroutine-engine && sh ./tutorial/runAlpine.sh
+CMD ["/usr/bin/supervisord"]
diff --git a/tutorial/conf/nginx.conf b/tutorial/conf/nginx.conf
new file mode 100644
index 00000000000..c8a67c641e3
--- /dev/null
+++ b/tutorial/conf/nginx.conf
@@ -0,0 +1,117 @@
+#user  nobody;
+worker_processes  8;
+
+#error_log  logs/error.log;
+#error_log  logs/error.log  notice;
+#error_log  logs/error.log  info;
+
+#pid        logs/nginx.pid;
+
+daemon off;
+
+events {
+    worker_connections  1024;
+}
+
+
+http {
+    include       mime.types;
+    default_type  application/octet-stream;
+
+    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+    #                  '$status $body_bytes_sent "$http_referer" '
+    #                  '"$http_user_agent" "$http_x_forwarded_for"';
+
+    #access_log  logs/access.log  main;
+
+    sendfile        on;
+    #tcp_nopush     on;
+
+    #keepalive_timeout  0;
+    keepalive_timeout  65;
+
+    #gzip  on;
+
+    server {
+        listen       80;
+        server_name  localhost;
+
+        #charset koi8-r;
+
+        #access_log  logs/host.access.log  main;
+
+        location / {
+            root   /data/www/;
+            index  index.html index.htm;
+        }
+
+        #error_page  404              /404.html;
+
+        # redirect server error pages to the static page /50x.html
+        #
+        error_page   500 502 503 504  /50x.html;
+        location = /50x.html {
+            root   html;
+        }
+
+        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
+        #
+        #location ~ \.php$ {
+        #    proxy_pass   http://127.0.0.1;
+        #}
+
+        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
+        #
+        location ~ \.php$ {
+            root           /data/www/;
+            fastcgi_pass   127.0.0.1:9000;
+            fastcgi_index  index.php;
+            fastcgi_param  SCRIPT_FILENAME  /data/www/$fastcgi_script_name;
+            include        fastcgi_params;
+        }
+
+        # deny access to .htaccess files, if Apache's document root
+        # concurs with nginx's one
+        #
+        #location ~ /\.ht {
+        #    deny  all;
+        #}
+    }
+
+
+    # another virtual host using mix of IP-, name-, and port-based configuration
+    #
+    #server {
+    #    listen       8000;
+    #    listen       somename:8080;
+    #    server_name  somename  alias  another.alias;
+
+    #    location / {
+    #        root   html;
+    #        index  index.html index.htm;
+    #    }
+    #}
+
+
+    # HTTPS server
+    #
+    #server {
+    #    listen       443 ssl;
+    #    server_name  localhost;
+
+    #    ssl_certificate      cert.pem;
+    #    ssl_certificate_key  cert.key;
+
+    #    ssl_session_cache    shared:SSL:1m;
+    #    ssl_session_timeout  5m;
+
+    #    ssl_ciphers  HIGH:!aNULL:!MD5;
+    #    ssl_prefer_server_ciphers  on;
+
+    #    location / {
+    #        root   html;
+    #        index  index.html index.htm;
+    #    }
+    #}
+
+}
\ No newline at end of file
diff --git a/tutorial/conf/php-fpm.conf b/tutorial/conf/php-fpm.conf
new file mode 100644
index 00000000000..ba6e9a261c7
--- /dev/null
+++ b/tutorial/conf/php-fpm.conf
@@ -0,0 +1,125 @@
+;;;;;;;;;;;;;;;;;;;;;
+; FPM Configuration ;
+;;;;;;;;;;;;;;;;;;;;;
+
+; All relative paths in this configuration file are relative to PHP's install
+; prefix (/usr/local/php7). This prefix can be dynamically changed by using the
+; '-p' argument from the command line.
+
+;;;;;;;;;;;;;;;;;;
+; Global Options ;
+;;;;;;;;;;;;;;;;;;
+
+[global]
+; Pid file
+; Note: the default prefix is /usr/local/php7/var
+; Default Value: none
+;pid = run/php-fpm.pid
+
+; Error log file
+; If it's set to "syslog", log is sent to syslogd instead of being written
+; into a local file.
+; Note: the default prefix is /usr/local/php7/var
+; Default Value: log/php-fpm.log
+;error_log = log/php-fpm.log
+
+; syslog_facility is used to specify what type of program is logging the
+; message. This lets syslogd specify that messages from different facilities
+; will be handled differently.
+; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON)
+; Default Value: daemon
+;syslog.facility = daemon
+
+; syslog_ident is prepended to every message. If you have multiple FPM
+; instances running on the same server, you can change the default value
+; which must suit common needs.
+; Default Value: php-fpm
+;syslog.ident = php-fpm
+
+; Log level
+; Possible Values: alert, error, warning, notice, debug
+; Default Value: notice
+;log_level = notice
+
+; If this number of child processes exit with SIGSEGV or SIGBUS within the time
+; interval set by emergency_restart_interval then FPM will restart. A value
+; of '0' means 'Off'.
+; Default Value: 0
+;emergency_restart_threshold = 0
+
+; Interval of time used by emergency_restart_interval to determine when
+; a graceful restart will be initiated.  This can be useful to work around
+; accidental corruptions in an accelerator's shared memory.
+; Available Units: s(econds), m(inutes), h(ours), or d(ays)
+; Default Unit: seconds
+; Default Value: 0
+;emergency_restart_interval = 0
+
+; Time limit for child processes to wait for a reaction on signals from master.
+; Available units: s(econds), m(inutes), h(ours), or d(ays)
+; Default Unit: seconds
+; Default Value: 0
+;process_control_timeout = 0
+
+; The maximum number of processes FPM will fork. This has been designed to control
+; the global number of processes when using dynamic PM within a lot of pools.
+; Use it with caution.
+; Note: A value of 0 indicates no limit
+; Default Value: 0
+; process.max = 128
+
+; Specify the nice(2) priority to apply to the master process (only if set)
+; The value can vary from -19 (highest priority) to 20 (lowest priority)
+; Note: - It will only work if the FPM master process is launched as root
+;       - The pool process will inherit the master process priority
+;         unless specified otherwise
+; Default Value: no set
+; process.priority = -19
+
+; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging.
+; Default Value: yes
+daemonize = no
+
+; Set open file descriptor rlimit for the master process.
+; Default Value: system defined value
+;rlimit_files = 1024
+
+; Set max core size rlimit for the master process.
+; Possible Values: 'unlimited' or an integer greater or equal to 0
+; Default Value: system defined value
+;rlimit_core = 0
+
+; Specify the event mechanism FPM will use. The following is available:
+; - select     (any POSIX os)
+; - poll       (any POSIX os)
+; - epoll      (linux >= 2.5.44)
+; - kqueue     (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0)
+; - /dev/poll  (Solaris >= 7)
+; - port       (Solaris >= 10)
+; Default Value: not set (auto detection)
+;events.mechanism = epoll
+
+; When FPM is built with systemd integration, specify the interval,
+; in seconds, between health report notification to systemd.
+; Set to 0 to disable.
+; Available Units: s(econds), m(inutes), h(ours)
+; Default Unit: seconds
+; Default value: 10
+;systemd_interval = 10
+
+;;;;;;;;;;;;;;;;;;;;
+; Pool Definitions ;
+;;;;;;;;;;;;;;;;;;;;
+
+; Multiple pools of child processes may be started with different listening
+; ports and different management options.  The name of the pool will be
+; used in logs and stats. There is no limitation on the number of pools which
+; FPM can handle. Your system will tell you anyway :)
+
+; Include one or more files. If glob(3) exists, it is used to include a bunch of
+; files from a glob(3) pattern. This directive can be used everywhere in the
+; file.
+; Relative path can also be used. They will be prefixed by:
+;  - the global prefix if it's been set (-p argument)
+;  - /usr/local/php7 otherwise
+include=/usr/local/php7/etc/php-fpm.d/*.conf
\ No newline at end of file
diff --git a/tutorial/conf/php.ini b/tutorial/conf/php.ini
new file mode 100644
index 00000000000..404ce5d703e
--- /dev/null
+++ b/tutorial/conf/php.ini
@@ -0,0 +1,1939 @@
+[PHP]
+
+;;;;;;;;;;;;;;;;;;;
+; About php.ini   ;
+;;;;;;;;;;;;;;;;;;;
+; PHP's initialization file, generally called php.ini, is responsible for
+; configuring many of the aspects of PHP's behavior.
+
+; PHP attempts to find and load this configuration from a number of locations.
+; The following is a summary of its search order:
+; 1. SAPI module specific location.
+; 2. The PHPRC environment variable. (As of PHP 5.2.0)
+; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0)
+; 4. Current working directory (except CLI)
+; 5. The web server's directory (for SAPI modules), or directory of PHP
+; (otherwise in Windows)
+; 6. The directory from the --with-config-file-path compile time option, or the
+; Windows directory (C:\windows or C:\winnt)
+; See the PHP docs for more specific information.
+; http://php.net/configuration.file
+
+; The syntax of the file is extremely simple.  Whitespace and lines
+; beginning with a semicolon are silently ignored (as you probably guessed).
+; Section headers (e.g. [Foo]) are also silently ignored, even though
+; they might mean something in the future.
+
+; Directives following the section heading [PATH=/www/mysite] only
+; apply to PHP files in the /www/mysite directory.  Directives
+; following the section heading [HOST=www.example.com] only apply to
+; PHP files served from www.example.com.  Directives set in these
+; special sections cannot be overridden by user-defined INI files or
+; at runtime. Currently, [PATH=] and [HOST=] sections only work under
+; CGI/FastCGI.
+; http://php.net/ini.sections
+
+; Directives are specified using the following syntax:
+; directive = value
+; Directive names are *case sensitive* - foo=bar is different from FOO=bar.
+; Directives are variables used to configure PHP or PHP extensions.
+; There is no name validation.  If PHP can't find an expected
+; directive because it is not set or is mistyped, a default value will be used.
+
+; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one
+; of the INI constants (On, Off, True, False, Yes, No and None) or an expression
+; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a
+; previously set variable or directive (e.g. ${foo})
+
+; Expressions in the INI file are limited to bitwise operators and parentheses:
+; |  bitwise OR
+; ^  bitwise XOR
+; &  bitwise AND
+; ~  bitwise NOT
+; !  boolean NOT
+
+; Boolean flags can be turned on using the values 1, On, True or Yes.
+; They can be turned off using the values 0, Off, False or No.
+
+; An empty string can be denoted by simply not writing anything after the equal
+; sign, or by using the None keyword:
+
+;  foo =         ; sets foo to an empty string
+;  foo = None    ; sets foo to an empty string
+;  foo = "None"  ; sets foo to the string 'None'
+
+; If you use constants in your value, and these constants belong to a
+; dynamically loaded extension (either a PHP extension or a Zend extension),
+; you may only use these constants *after* the line that loads the extension.
+
+;;;;;;;;;;;;;;;;;;;
+; About this file ;
+;;;;;;;;;;;;;;;;;;;
+; PHP comes packaged with two INI files. One that is recommended to be used
+; in production environments and one that is recommended to be used in
+; development environments.
+
+; php.ini-production contains settings which hold security, performance and
+; best practices at its core. But please be aware, these settings may break
+; compatibility with older or less security conscience applications. We
+; recommending using the production ini in production and testing environments.
+
+; php.ini-development is very similar to its production variant, except it is
+; much more verbose when it comes to errors. We recommend using the
+; development version only in development environments, as errors shown to
+; application users can inadvertently leak otherwise secure information.
+
+; This is php.ini-development INI file.
+
+;;;;;;;;;;;;;;;;;;;
+; Quick Reference ;
+;;;;;;;;;;;;;;;;;;;
+; The following are all the settings which are different in either the production
+; or development versions of the INIs with respect to PHP's default behavior.
+; Please see the actual settings later in the document for more details as to why
+; we recommend these changes in PHP's behavior.
+
+; display_errors
+;   Default Value: On
+;   Development Value: On
+;   Production Value: Off
+
+; display_startup_errors
+;   Default Value: Off
+;   Development Value: On
+;   Production Value: Off
+
+; error_reporting
+;   Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
+;   Development Value: E_ALL
+;   Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
+
+; html_errors
+;   Default Value: On
+;   Development Value: On
+;   Production value: On
+
+; log_errors
+;   Default Value: Off
+;   Development Value: On
+;   Production Value: On
+
+; max_input_time
+;   Default Value: -1 (Unlimited)
+;   Development Value: 60 (60 seconds)
+;   Production Value: 60 (60 seconds)
+
+; output_buffering
+;   Default Value: Off
+;   Development Value: 4096
+;   Production Value: 4096
+
+; register_argc_argv
+;   Default Value: On
+;   Development Value: Off
+;   Production Value: Off
+
+; request_order
+;   Default Value: None
+;   Development Value: "GP"
+;   Production Value: "GP"
+
+; session.gc_divisor
+;   Default Value: 100
+;   Development Value: 1000
+;   Production Value: 1000
+
+; session.sid_bits_per_character
+;   Default Value: 4
+;   Development Value: 5
+;   Production Value: 5
+
+; short_open_tag
+;   Default Value: On
+;   Development Value: Off
+;   Production Value: Off
+
+; track_errors
+;   Default Value: Off
+;   Development Value: On
+;   Production Value: Off
+
+; variables_order
+;   Default Value: "EGPCS"
+;   Development Value: "GPCS"
+;   Production Value: "GPCS"
+
+;;;;;;;;;;;;;;;;;;;;
+; php.ini Options  ;
+;;;;;;;;;;;;;;;;;;;;
+; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini"
+;user_ini.filename = ".user.ini"
+
+; To disable this feature set this option to empty value
+;user_ini.filename =
+
+; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes)
+;user_ini.cache_ttl = 300
+
+;;;;;;;;;;;;;;;;;;;;
+; Language Options ;
+;;;;;;;;;;;;;;;;;;;;
+
+; Enable the PHP scripting language engine under Apache.
+; http://php.net/engine
+engine = On
+
+; This directive determines whether or not PHP will recognize code between
+; <? and ?> tags as PHP source which should be processed as such. It is
+; generally recommended that <?php and ?> should be used and that this feature
+; should be disabled, as enabling it may result in issues when generating XML
+; documents, however this remains supported for backward compatibility reasons.
+; Note that this directive does not control the <?= shorthand tag, which can be
+; used regardless of this directive.
+; Default Value: On
+; Development Value: Off
+; Production Value: Off
+; http://php.net/short-open-tag
+short_open_tag = Off
+
+; The number of significant digits displayed in floating point numbers.
+; http://php.net/precision
+precision = 14
+
+; Output buffering is a mechanism for controlling how much output data
+; (excluding headers and cookies) PHP should keep internally before pushing that
+; data to the client. If your application's output exceeds this setting, PHP
+; will send that data in chunks of roughly the size you specify.
+; Turning on this setting and managing its maximum buffer size can yield some
+; interesting side-effects depending on your application and web server.
+; You may be able to send headers and cookies after you've already sent output
+; through print or echo. You also may see performance benefits if your server is
+; emitting less packets due to buffered output versus PHP streaming the output
+; as it gets it. On production servers, 4096 bytes is a good setting for performance
+; reasons.
+; Note: Output buffering can also be controlled via Output Buffering Control
+;   functions.
+; Possible Values:
+;   On = Enabled and buffer is unlimited. (Use with caution)
+;   Off = Disabled
+;   Integer = Enables the buffer and sets its maximum size in bytes.
+; Note: This directive is hardcoded to Off for the CLI SAPI
+; Default Value: Off
+; Development Value: 4096
+; Production Value: 4096
+; http://php.net/output-buffering
+output_buffering = 4096
+
+; You can redirect all of the output of your scripts to a function.  For
+; example, if you set output_handler to "mb_output_handler", character
+; encoding will be transparently converted to the specified encoding.
+; Setting any output handler automatically turns on output buffering.
+; Note: People who wrote portable scripts should not depend on this ini
+;   directive. Instead, explicitly set the output handler using ob_start().
+;   Using this ini directive may cause problems unless you know what script
+;   is doing.
+; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler"
+;   and you cannot use both "ob_gzhandler" and "zlib.output_compression".
+; Note: output_handler must be empty if this is set 'On' !!!!
+;   Instead you must use zlib.output_handler.
+; http://php.net/output-handler
+;output_handler =
+
+; URL rewriter function rewrites URL on the fly by using
+; output buffer. You can set target tags by this configuration.
+; "form" tag is special tag. It will add hidden input tag to pass values.
+; Refer to session.trans_sid_tags for usage.
+; Default Value: "form="
+; Development Value: "form="
+; Production Value: "form="
+;url_rewriter.tags
+
+; URL rewriter will not rewrites absolute URL nor form by default. To enable
+; absolute URL rewrite, allowed hosts must be defined at RUNTIME.
+; Refer to session.trans_sid_hosts for more details.
+; Default Value: ""
+; Development Value: ""
+; Production Value: ""
+;url_rewriter.hosts
+
+; Transparent output compression using the zlib library
+; Valid values for this option are 'off', 'on', or a specific buffer size
+; to be used for compression (default is 4KB)
+; Note: Resulting chunk size may vary due to nature of compression. PHP
+;   outputs chunks that are few hundreds bytes each as a result of
+;   compression. If you prefer a larger chunk size for better
+;   performance, enable output_buffering in addition.
+; Note: You need to use zlib.output_handler instead of the standard
+;   output_handler, or otherwise the output will be corrupted.
+; http://php.net/zlib.output-compression
+zlib.output_compression = Off
+
+; http://php.net/zlib.output-compression-level
+;zlib.output_compression_level = -1
+
+; You cannot specify additional output handlers if zlib.output_compression
+; is activated here. This setting does the same as output_handler but in
+; a different order.
+; http://php.net/zlib.output-handler
+;zlib.output_handler =
+
+; Implicit flush tells PHP to tell the output layer to flush itself
+; automatically after every output block.  This is equivalent to calling the
+; PHP function flush() after each and every call to print() or echo() and each
+; and every HTML block.  Turning this option on has serious performance
+; implications and is generally recommended for debugging purposes only.
+; http://php.net/implicit-flush
+; Note: This directive is hardcoded to On for the CLI SAPI
+implicit_flush = Off
+
+; The unserialize callback function will be called (with the undefined class'
+; name as parameter), if the unserializer finds an undefined class
+; which should be instantiated. A warning appears if the specified function is
+; not defined, or if the function doesn't include/implement the missing class.
+; So only set this entry, if you really want to implement such a
+; callback-function.
+unserialize_callback_func =
+
+; When floats & doubles are serialized store serialize_precision significant
+; digits after the floating point. The default value ensures that when floats
+; are decoded with unserialize, the data will remain the same.
+; The value is also used for json_encode when encoding double values.
+; If -1 is used, then dtoa mode 0 is used which automatically select the best
+; precision.
+serialize_precision = -1
+
+; open_basedir, if set, limits all file operations to the defined directory
+; and below.  This directive makes most sense if used in a per-directory
+; or per-virtualhost web server configuration file.
+; http://php.net/open-basedir
+;open_basedir =
+
+; This directive allows you to disable certain functions for security reasons.
+; It receives a comma-delimited list of function names.
+; http://php.net/disable-functions
+disable_functions =
+
+; This directive allows you to disable certain classes for security reasons.
+; It receives a comma-delimited list of class names.
+; http://php.net/disable-classes
+disable_classes =
+
+; Colors for Syntax Highlighting mode.  Anything that's acceptable in
+; <span style="color: ???????"> would work.
+; http://php.net/syntax-highlighting
+;highlight.string  = #DD0000
+;highlight.comment = #FF9900
+;highlight.keyword = #007700
+;highlight.default = #0000BB
+;highlight.html    = #000000
+
+; If enabled, the request will be allowed to complete even if the user aborts
+; the request. Consider enabling it if executing long requests, which may end up
+; being interrupted by the user or a browser timing out. PHP's default behavior
+; is to disable this feature.
+; http://php.net/ignore-user-abort
+;ignore_user_abort = On
+
+; Determines the size of the realpath cache to be used by PHP. This value should
+; be increased on systems where PHP opens many files to reflect the quantity of
+; the file operations performed.
+; http://php.net/realpath-cache-size
+;realpath_cache_size = 4096k
+
+; Duration of time, in seconds for which to cache realpath information for a given
+; file or directory. For systems with rarely changing files, consider increasing this
+; value.
+; http://php.net/realpath-cache-ttl
+;realpath_cache_ttl = 120
+
+; Enables or disables the circular reference collector.
+; http://php.net/zend.enable-gc
+zend.enable_gc = On
+
+; If enabled, scripts may be written in encodings that are incompatible with
+; the scanner.  CP936, Big5, CP949 and Shift_JIS are the examples of such
+; encodings.  To use this feature, mbstring extension must be enabled.
+; Default: Off
+;zend.multibyte = Off
+
+; Allows to set the default encoding for the scripts.  This value will be used
+; unless "declare(encoding=...)" directive appears at the top of the script.
+; Only affects if zend.multibyte is set.
+; Default: ""
+;zend.script_encoding =
+
+;;;;;;;;;;;;;;;;;
+; Miscellaneous ;
+;;;;;;;;;;;;;;;;;
+
+; Decides whether PHP may expose the fact that it is installed on the server
+; (e.g. by adding its signature to the Web server header).  It is no security
+; threat in any way, but it makes it possible to determine whether you use PHP
+; on your server or not.
+; http://php.net/expose-php
+expose_php = On
+
+;;;;;;;;;;;;;;;;;;;
+; Resource Limits ;
+;;;;;;;;;;;;;;;;;;;
+
+; Maximum execution time of each script, in seconds
+; http://php.net/max-execution-time
+; Note: This directive is hardcoded to 0 for the CLI SAPI
+max_execution_time = 300
+
+; Maximum amount of time each script may spend parsing request data. It's a good
+; idea to limit this time on productions servers in order to eliminate unexpectedly
+; long running scripts.
+; Note: This directive is hardcoded to -1 for the CLI SAPI
+; Default Value: -1 (Unlimited)
+; Development Value: 60 (60 seconds)
+; Production Value: 60 (60 seconds)
+; http://php.net/max-input-time
+max_input_time = 60
+
+; Maximum input variable nesting level
+; http://php.net/max-input-nesting-level
+;max_input_nesting_level = 64
+
+; How many GET/POST/COOKIE input variables may be accepted
+; max_input_vars = 1000
+
+; Maximum amount of memory a script may consume (128MB)
+; http://php.net/memory-limit
+memory_limit = 128M
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Error handling and logging ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; This directive informs PHP of which errors, warnings and notices you would like
+; it to take action for. The recommended way of setting values for this
+; directive is through the use of the error level constants and bitwise
+; operators. The error level constants are below here for convenience as well as
+; some common settings and their meanings.
+; By default, PHP is set to take action on all errors, notices and warnings EXCEPT
+; those related to E_NOTICE and E_STRICT, which together cover best practices and
+; recommended coding standards in PHP. For performance reasons, this is the
+; recommend error reporting setting. Your production server shouldn't be wasting
+; resources complaining about best practices and coding standards. That's what
+; development servers and development settings are for.
+; Note: The php.ini-development file has this setting as E_ALL. This
+; means it pretty much reports everything which is exactly what you want during
+; development and early testing.
+;
+; Error Level Constants:
+; E_ALL             - All errors and warnings (includes E_STRICT as of PHP 5.4.0)
+; E_ERROR           - fatal run-time errors
+; E_RECOVERABLE_ERROR  - almost fatal run-time errors
+; E_WARNING         - run-time warnings (non-fatal errors)
+; E_PARSE           - compile-time parse errors
+; E_NOTICE          - run-time notices (these are warnings which often result
+;                     from a bug in your code, but it's possible that it was
+;                     intentional (e.g., using an uninitialized variable and
+;                     relying on the fact it is automatically initialized to an
+;                     empty string)
+; E_STRICT          - run-time notices, enable to have PHP suggest changes
+;                     to your code which will ensure the best interoperability
+;                     and forward compatibility of your code
+; E_CORE_ERROR      - fatal errors that occur during PHP's initial startup
+; E_CORE_WARNING    - warnings (non-fatal errors) that occur during PHP's
+;                     initial startup
+; E_COMPILE_ERROR   - fatal compile-time errors
+; E_COMPILE_WARNING - compile-time warnings (non-fatal errors)
+; E_USER_ERROR      - user-generated error message
+; E_USER_WARNING    - user-generated warning message
+; E_USER_NOTICE     - user-generated notice message
+; E_DEPRECATED      - warn about code that will not work in future versions
+;                     of PHP
+; E_USER_DEPRECATED - user-generated deprecation warnings
+;
+; Common Values:
+;   E_ALL (Show all errors, warnings and notices including coding standards.)
+;   E_ALL & ~E_NOTICE  (Show all errors, except for notices)
+;   E_ALL & ~E_NOTICE & ~E_STRICT  (Show all errors, except for notices and coding standards warnings.)
+;   E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR  (Show only errors)
+; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
+; Development Value: E_ALL
+; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
+; http://php.net/error-reporting
+error_reporting = E_ALL
+
+; This directive controls whether or not and where PHP will output errors,
+; notices and warnings too. Error output is very useful during development, but
+; it could be very dangerous in production environments. Depending on the code
+; which is triggering the error, sensitive information could potentially leak
+; out of your application such as database usernames and passwords or worse.
+; For production environments, we recommend logging errors rather than
+; sending them to STDOUT.
+; Possible Values:
+;   Off = Do not display any errors
+;   stderr = Display errors to STDERR (affects only CGI/CLI binaries!)
+;   On or stdout = Display errors to STDOUT
+; Default Value: On
+; Development Value: On
+; Production Value: Off
+; http://php.net/display-errors
+display_errors = On
+
+; The display of errors which occur during PHP's startup sequence are handled
+; separately from display_errors. PHP's default behavior is to suppress those
+; errors from clients. Turning the display of startup errors on can be useful in
+; debugging configuration problems. We strongly recommend you
+; set this to 'off' for production servers.
+; Default Value: Off
+; Development Value: On
+; Production Value: Off
+; http://php.net/display-startup-errors
+display_startup_errors = On
+
+; Besides displaying errors, PHP can also log errors to locations such as a
+; server-specific log, STDERR, or a location specified by the error_log
+; directive found below. While errors should not be displayed on productions
+; servers they should still be monitored and logging is a great way to do that.
+; Default Value: Off
+; Development Value: On
+; Production Value: On
+; http://php.net/log-errors
+log_errors = On
+
+; Set maximum length of log_errors. In error_log information about the source is
+; added. The default is 1024 and 0 allows to not apply any maximum length at all.
+; http://php.net/log-errors-max-len
+log_errors_max_len = 1024
+
+; Do not log repeated messages. Repeated errors must occur in same file on same
+; line unless ignore_repeated_source is set true.
+; http://php.net/ignore-repeated-errors
+ignore_repeated_errors = Off
+
+; Ignore source of message when ignoring repeated messages. When this setting
+; is On you will not log errors with repeated messages from different files or
+; source lines.
+; http://php.net/ignore-repeated-source
+ignore_repeated_source = Off
+
+; If this parameter is set to Off, then memory leaks will not be shown (on
+; stdout or in the log). This has only effect in a debug compile, and if
+; error reporting includes E_WARNING in the allowed list
+; http://php.net/report-memleaks
+report_memleaks = On
+
+; This setting is on by default.
+;report_zend_debug = 0
+
+; Store the last error/warning message in $php_errormsg (boolean). Setting this value
+; to On can assist in debugging and is appropriate for development servers. It should
+; however be disabled on production servers.
+; Default Value: Off
+; Development Value: On
+; Production Value: Off
+; http://php.net/track-errors
+track_errors = On
+
+; Turn off normal error reporting and emit XML-RPC error XML
+; http://php.net/xmlrpc-errors
+;xmlrpc_errors = 0
+
+; An XML-RPC faultCode
+;xmlrpc_error_number = 0
+
+; When PHP displays or logs an error, it has the capability of formatting the
+; error message as HTML for easier reading. This directive controls whether
+; the error message is formatted as HTML or not.
+; Note: This directive is hardcoded to Off for the CLI SAPI
+; Default Value: On
+; Development Value: On
+; Production value: On
+; http://php.net/html-errors
+html_errors = On
+
+; If html_errors is set to On *and* docref_root is not empty, then PHP
+; produces clickable error messages that direct to a page describing the error
+; or function causing the error in detail.
+; You can download a copy of the PHP manual from http://php.net/docs
+; and change docref_root to the base URL of your local copy including the
+; leading '/'. You must also specify the file extension being used including
+; the dot. PHP's default behavior is to leave these settings empty, in which
+; case no links to documentation are generated.
+; Note: Never use this feature for production boxes.
+; http://php.net/docref-root
+; Examples
+;docref_root = "/phpmanual/"
+
+; http://php.net/docref-ext
+;docref_ext = .html
+
+; String to output before an error message. PHP's default behavior is to leave
+; this setting blank.
+; http://php.net/error-prepend-string
+; Example:
+;error_prepend_string = "<span style='color: #ff0000'>"
+
+; String to output after an error message. PHP's default behavior is to leave
+; this setting blank.
+; http://php.net/error-append-string
+; Example:
+;error_append_string = "</span>"
+
+; Log errors to specified file. PHP's default behavior is to leave this value
+; empty.
+; http://php.net/error-log
+; Example:
+;error_log = php_errors.log
+; Log errors to syslog (Event Log on Windows).
+;error_log = syslog
+
+;windows.show_crt_warning
+; Default value: 0
+; Development value: 0
+; Production value: 0
+
+;;;;;;;;;;;;;;;;;
+; Data Handling ;
+;;;;;;;;;;;;;;;;;
+
+; The separator used in PHP generated URLs to separate arguments.
+; PHP's default setting is "&".
+; http://php.net/arg-separator.output
+; Example:
+;arg_separator.output = "&amp;"
+
+; List of separator(s) used by PHP to parse input URLs into variables.
+; PHP's default setting is "&".
+; NOTE: Every character in this directive is considered as separator!
+; http://php.net/arg-separator.input
+; Example:
+;arg_separator.input = ";&"
+
+; This directive determines which super global arrays are registered when PHP
+; starts up. G,P,C,E & S are abbreviations for the following respective super
+; globals: GET, POST, COOKIE, ENV and SERVER. There is a performance penalty
+; paid for the registration of these arrays and because ENV is not as commonly
+; used as the others, ENV is not recommended on productions servers. You
+; can still get access to the environment variables through getenv() should you
+; need to.
+; Default Value: "EGPCS"
+; Development Value: "GPCS"
+; Production Value: "GPCS";
+; http://php.net/variables-order
+variables_order = "GPCS"
+
+; This directive determines which super global data (G,P & C) should be
+; registered into the super global array REQUEST. If so, it also determines
+; the order in which that data is registered. The values for this directive
+; are specified in the same manner as the variables_order directive,
+; EXCEPT one. Leaving this value empty will cause PHP to use the value set
+; in the variables_order directive. It does not mean it will leave the super
+; globals array REQUEST empty.
+; Default Value: None
+; Development Value: "GP"
+; Production Value: "GP"
+; http://php.net/request-order
+request_order = "GP"
+
+; This directive determines whether PHP registers $argv & $argc each time it
+; runs. $argv contains an array of all the arguments passed to PHP when a script
+; is invoked. $argc contains an integer representing the number of arguments
+; that were passed when the script was invoked. These arrays are extremely
+; useful when running scripts from the command line. When this directive is
+; enabled, registering these variables consumes CPU cycles and memory each time
+; a script is executed. For performance reasons, this feature should be disabled
+; on production servers.
+; Note: This directive is hardcoded to On for the CLI SAPI
+; Default Value: On
+; Development Value: Off
+; Production Value: Off
+; http://php.net/register-argc-argv
+register_argc_argv = Off
+
+; When enabled, the ENV, REQUEST and SERVER variables are created when they're
+; first used (Just In Time) instead of when the script starts. If these
+; variables are not used within a script, having this directive on will result
+; in a performance gain. The PHP directive register_argc_argv must be disabled
+; for this directive to have any affect.
+; http://php.net/auto-globals-jit
+auto_globals_jit = On
+
+; Whether PHP will read the POST data.
+; This option is enabled by default.
+; Most likely, you won't want to disable this option globally. It causes $_POST
+; and $_FILES to always be empty; the only way you will be able to read the
+; POST data will be through the php://input stream wrapper. This can be useful
+; to proxy requests or to process the POST data in a memory efficient fashion.
+; http://php.net/enable-post-data-reading
+;enable_post_data_reading = Off
+
+; Maximum size of POST data that PHP will accept.
+; Its value may be 0 to disable the limit. It is ignored if POST data reading
+; is disabled through enable_post_data_reading.
+; http://php.net/post-max-size
+post_max_size = 8M
+
+; Automatically add files before PHP document.
+; http://php.net/auto-prepend-file
+auto_prepend_file =
+
+; Automatically add files after PHP document.
+; http://php.net/auto-append-file
+auto_append_file =
+
+; By default, PHP will output a media type using the Content-Type header. To
+; disable this, simply set it to be empty.
+;
+; PHP's built-in default media type is set to text/html.
+; http://php.net/default-mimetype
+default_mimetype = "text/html"
+
+; PHP's default character set is set to UTF-8.
+; http://php.net/default-charset
+default_charset = "UTF-8"
+
+; PHP internal character encoding is set to empty.
+; If empty, default_charset is used.
+; http://php.net/internal-encoding
+;internal_encoding =
+
+; PHP input character encoding is set to empty.
+; If empty, default_charset is used.
+; http://php.net/input-encoding
+;input_encoding =
+
+; PHP output character encoding is set to empty.
+; If empty, default_charset is used.
+; See also output_buffer.
+; http://php.net/output-encoding
+;output_encoding =
+
+;;;;;;;;;;;;;;;;;;;;;;;;;
+; Paths and Directories ;
+;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; UNIX: "/path1:/path2"
+;include_path = ".:/php/includes"
+;
+; Windows: "\path1;\path2"
+;include_path = ".;c:\php\includes"
+;
+; PHP's default setting for include_path is ".;/path/to/php/pear"
+; http://php.net/include-path
+
+; The root of the PHP pages, used only if nonempty.
+; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root
+; if you are running php as a CGI under any web server (other than IIS)
+; see documentation for security issues.  The alternate is to use the
+; cgi.force_redirect configuration below
+; http://php.net/doc-root
+doc_root =
+
+; The directory under which PHP opens the script using /~username used only
+; if nonempty.
+; http://php.net/user-dir
+user_dir =
+
+; Directory in which the loadable extensions (modules) reside.
+; http://php.net/extension-dir
+; extension_dir = "./"
+; On windows:
+; extension_dir = "ext"
+
+; Directory where the temporary files should be placed.
+; Defaults to the system default (see sys_get_temp_dir)
+; sys_temp_dir = "/tmp"
+
+; Whether or not to enable the dl() function.  The dl() function does NOT work
+; properly in multithreaded servers, such as IIS or Zeus, and is automatically
+; disabled on them.
+; http://php.net/enable-dl
+enable_dl = Off
+
+; cgi.force_redirect is necessary to provide security running PHP as a CGI under
+; most web servers.  Left undefined, PHP turns this on by default.  You can
+; turn it off here AT YOUR OWN RISK
+; **You CAN safely turn this off for IIS, in fact, you MUST.**
+; http://php.net/cgi.force-redirect
+;cgi.force_redirect = 1
+
+; if cgi.nph is enabled it will force cgi to always sent Status: 200 with
+; every request. PHP's default behavior is to disable this feature.
+;cgi.nph = 1
+
+; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape
+; (iPlanet) web servers, you MAY need to set an environment variable name that PHP
+; will look for to know it is OK to continue execution.  Setting this variable MAY
+; cause security issues, KNOW WHAT YOU ARE DOING FIRST.
+; http://php.net/cgi.redirect-status-env
+;cgi.redirect_status_env =
+
+; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI.  PHP's
+; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
+; what PATH_INFO is.  For more information on PATH_INFO, see the cgi specs.  Setting
+; this to 1 will cause PHP CGI to fix its paths to conform to the spec.  A setting
+; of zero causes PHP to behave as before.  Default is 1.  You should fix your scripts
+; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.
+; http://php.net/cgi.fix-pathinfo
+;cgi.fix_pathinfo=1
+
+; if cgi.discard_path is enabled, the PHP CGI binary can safely be placed outside
+; of the web tree and people will not be able to circumvent .htaccess security.
+; http://php.net/cgi.dicard-path
+;cgi.discard_path=1
+
+; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate
+; security tokens of the calling client.  This allows IIS to define the
+; security context that the request runs under.  mod_fastcgi under Apache
+; does not currently support this feature (03/17/2002)
+; Set to 1 if running under IIS.  Default is zero.
+; http://php.net/fastcgi.impersonate
+;fastcgi.impersonate = 1
+
+; Disable logging through FastCGI connection. PHP's default behavior is to enable
+; this feature.
+;fastcgi.logging = 0
+
+; cgi.rfc2616_headers configuration option tells PHP what type of headers to
+; use when sending HTTP response code. If set to 0, PHP sends Status: header that
+; is supported by Apache. When this option is set to 1, PHP will send
+; RFC2616 compliant header.
+; Default is zero.
+; http://php.net/cgi.rfc2616-headers
+;cgi.rfc2616_headers = 0
+
+; cgi.check_shebang_line controls whether CGI PHP checks for line starting with #!
+; (shebang) at the top of the running script. This line might be needed if the
+; script support running both as stand-alone script and via PHP CGI<. PHP in CGI
+; mode skips this line and ignores its content if this directive is turned on.
+; http://php.net/cgi.check-shebang-line
+;cgi.check_shebang_line=1
+
+;;;;;;;;;;;;;;;;
+; File Uploads ;
+;;;;;;;;;;;;;;;;
+
+; Whether to allow HTTP file uploads.
+; http://php.net/file-uploads
+file_uploads = On
+
+; Temporary directory for HTTP uploaded files (will use system default if not
+; specified).
+; http://php.net/upload-tmp-dir
+;upload_tmp_dir =
+
+; Maximum allowed size for uploaded files.
+; http://php.net/upload-max-filesize
+upload_max_filesize = 2M
+
+; Maximum number of files that can be uploaded via a single request
+max_file_uploads = 20
+
+;;;;;;;;;;;;;;;;;;
+; Fopen wrappers ;
+;;;;;;;;;;;;;;;;;;
+
+; Whether to allow the treatment of URLs (like http:// or ftp://) as files.
+; http://php.net/allow-url-fopen
+allow_url_fopen = On
+
+; Whether to allow include/require to open URLs (like http:// or ftp://) as files.
+; http://php.net/allow-url-include
+allow_url_include = Off
+
+; Define the anonymous ftp password (your email address). PHP's default setting
+; for this is empty.
+; http://php.net/from
+;from="john@doe.com"
+
+; Define the User-Agent string. PHP's default setting for this is empty.
+; http://php.net/user-agent
+;user_agent="PHP"
+
+; Default timeout for socket based streams (seconds)
+; http://php.net/default-socket-timeout
+default_socket_timeout = 60
+
+; If your scripts have to deal with files from Macintosh systems,
+; or you are running on a Mac and need to deal with files from
+; unix or win32 systems, setting this flag will cause PHP to
+; automatically detect the EOL character in those files so that
+; fgets() and file() will work regardless of the source of the file.
+; http://php.net/auto-detect-line-endings
+;auto_detect_line_endings = Off
+
+;;;;;;;;;;;;;;;;;;;;;;
+; Dynamic Extensions ;
+;;;;;;;;;;;;;;;;;;;;;;
+
+; If you wish to have an extension loaded automatically, use the following
+; syntax:
+;
+;   extension=modulename.extension
+;
+; For example, on Windows:
+;
+;   extension=msql.dll
+;
+; ... or under UNIX:
+;
+;   extension=msql.so
+;
+; ... or with a path:
+;
+;   extension=/path/to/extension/msql.so
+;
+; If you only provide the name of the extension, PHP will look for it in its
+; default extension directory.
+;
+; Windows Extensions
+; Note that ODBC support is built in, so no dll is needed for it.
+; Note that many DLL files are located in the extensions/ (PHP 4) ext/ (PHP 5+)
+; extension folders as well as the separate PECL DLL download (PHP 5+).
+; Be sure to appropriately set the extension_dir directive.
+;
+;extension=php_bz2.dll
+;extension=php_curl.dll
+;extension=php_fileinfo.dll
+;extension=php_ftp.dll
+;extension=php_gd2.dll
+;extension=php_gettext.dll
+;extension=php_gmp.dll
+;extension=php_intl.dll
+;extension=php_imap.dll
+;extension=php_interbase.dll
+;extension=php_ldap.dll
+;extension=php_mbstring.dll
+;extension=php_exif.dll      ; Must be after mbstring as it depends on it
+;extension=php_mysqli.dll
+;extension=php_oci8_12c.dll  ; Use with Oracle Database 12c Instant Client
+;extension=php_openssl.dll
+;extension=php_pdo_firebird.dll
+;extension=php_pdo_mysql.dll
+;extension=php_pdo_oci.dll
+;extension=php_pdo_odbc.dll
+;extension=php_pdo_pgsql.dll
+;extension=php_pdo_sqlite.dll
+;extension=php_pgsql.dll
+;extension=php_shmop.dll
+
+; The MIBS data available in the PHP distribution must be installed.
+; See http://www.php.net/manual/en/snmp.installation.php
+;extension=php_snmp.dll
+
+;extension=php_soap.dll
+;extension=php_sockets.dll
+;extension=php_sqlite3.dll
+;extension=php_tidy.dll
+;extension=php_xmlrpc.dll
+;extension=php_xsl.dll
+;extension=/Users/sioomy/work/php-src/ext/coro_http/modules/coro_http.so
+;extension=/usr/local/php7/lib/php/extensions/no-debug-zts-20160303/coro_http.so
+;extension=/Users/sioomy/Downloads/php-7.1.15/ext/coroutine_php/modules/coroutine_php.so
+
+;;;;;;;;;;;;;;;;;;;
+; Module Settings ;
+;;;;;;;;;;;;;;;;;;;
+
+[CLI Server]
+; Whether the CLI web server uses ANSI color coding in its terminal output.
+cli_server.color = On
+
+[Date]
+; Defines the default timezone used by the date functions
+; http://php.net/date.timezone
+;date.timezone =
+
+; http://php.net/date.default-latitude
+;date.default_latitude = 31.7667
+
+; http://php.net/date.default-longitude
+;date.default_longitude = 35.2333
+
+; http://php.net/date.sunrise-zenith
+;date.sunrise_zenith = 90.583333
+
+; http://php.net/date.sunset-zenith
+;date.sunset_zenith = 90.583333
+
+[filter]
+; http://php.net/filter.default
+;filter.default = unsafe_raw
+
+; http://php.net/filter.default-flags
+;filter.default_flags =
+
+[iconv]
+; Use of this INI entry is deprecated, use global input_encoding instead.
+; If empty, default_charset or input_encoding or iconv.input_encoding is used.
+; The precedence is: default_charset < intput_encoding < iconv.input_encoding
+;iconv.input_encoding =
+
+; Use of this INI entry is deprecated, use global internal_encoding instead.
+; If empty, default_charset or internal_encoding or iconv.internal_encoding is used.
+; The precedence is: default_charset < internal_encoding < iconv.internal_encoding
+;iconv.internal_encoding =
+
+; Use of this INI entry is deprecated, use global output_encoding instead.
+; If empty, default_charset or output_encoding or iconv.output_encoding is used.
+; The precedence is: default_charset < output_encoding < iconv.output_encoding
+; To use an output encoding conversion, iconv's output handler must be set
+; otherwise output encoding conversion cannot be performed.
+;iconv.output_encoding =
+
+[intl]
+;intl.default_locale =
+; This directive allows you to produce PHP errors when some error
+; happens within intl functions. The value is the level of the error produced.
+; Default is 0, which does not produce any errors.
+;intl.error_level = E_WARNING
+;intl.use_exceptions = 0
+
+[sqlite3]
+;sqlite3.extension_dir =
+
+[Pcre]
+;PCRE library backtracking limit.
+; http://php.net/pcre.backtrack-limit
+;pcre.backtrack_limit=100000
+
+;PCRE library recursion limit.
+;Please note that if you set this value to a high number you may consume all
+;the available process stack and eventually crash PHP (due to reaching the
+;stack size limit imposed by the Operating System).
+; http://php.net/pcre.recursion-limit
+;pcre.recursion_limit=100000
+
+;Enables or disables JIT compilation of patterns. This requires the PCRE
+;library to be compiled with JIT support.
+;pcre.jit=1
+
+[Pdo]
+; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off"
+; http://php.net/pdo-odbc.connection-pooling
+;pdo_odbc.connection_pooling=strict
+
+;pdo_odbc.db2_instance_name
+
+[Pdo_mysql]
+; If mysqlnd is used: Number of cache slots for the internal result set cache
+; http://php.net/pdo_mysql.cache_size
+pdo_mysql.cache_size = 2000
+
+; Default socket name for local MySQL connects.  If empty, uses the built-in
+; MySQL defaults.
+; http://php.net/pdo_mysql.default-socket
+pdo_mysql.default_socket=
+
+[Phar]
+; http://php.net/phar.readonly
+;phar.readonly = On
+
+; http://php.net/phar.require-hash
+;phar.require_hash = On
+
+;phar.cache_list =
+
+[mail function]
+; For Win32 only.
+; http://php.net/smtp
+SMTP = localhost
+; http://php.net/smtp-port
+smtp_port = 25
+
+; For Win32 only.
+; http://php.net/sendmail-from
+;sendmail_from = me@example.com
+
+; For Unix only.  You may supply arguments as well (default: "sendmail -t -i").
+; http://php.net/sendmail-path
+;sendmail_path =
+
+; Force the addition of the specified parameters to be passed as extra parameters
+; to the sendmail binary. These parameters will always replace the value of
+; the 5th parameter to mail().
+;mail.force_extra_parameters =
+
+; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename
+mail.add_x_header = On
+
+; The path to a log file that will log all mail() calls. Log entries include
+; the full path of the script, line number, To address and headers.
+;mail.log =
+; Log mail to syslog (Event Log on Windows).
+;mail.log = syslog
+
+[SQL]
+; http://php.net/sql.safe-mode
+sql.safe_mode = Off
+
+[ODBC]
+; http://php.net/odbc.default-db
+;odbc.default_db    =  Not yet implemented
+
+; http://php.net/odbc.default-user
+;odbc.default_user  =  Not yet implemented
+
+; http://php.net/odbc.default-pw
+;odbc.default_pw    =  Not yet implemented
+
+; Controls the ODBC cursor model.
+; Default: SQL_CURSOR_STATIC (default).
+;odbc.default_cursortype
+
+; Allow or prevent persistent links.
+; http://php.net/odbc.allow-persistent
+odbc.allow_persistent = On
+
+; Check that a connection is still valid before reuse.
+; http://php.net/odbc.check-persistent
+odbc.check_persistent = On
+
+; Maximum number of persistent links.  -1 means no limit.
+; http://php.net/odbc.max-persistent
+odbc.max_persistent = -1
+
+; Maximum number of links (persistent + non-persistent).  -1 means no limit.
+; http://php.net/odbc.max-links
+odbc.max_links = -1
+
+; Handling of LONG fields.  Returns number of bytes to variables.  0 means
+; passthru.
+; http://php.net/odbc.defaultlrl
+odbc.defaultlrl = 4096
+
+; Handling of binary data.  0 means passthru, 1 return as is, 2 convert to char.
+; See the documentation on odbc_binmode and odbc_longreadlen for an explanation
+; of odbc.defaultlrl and odbc.defaultbinmode
+; http://php.net/odbc.defaultbinmode
+odbc.defaultbinmode = 1
+
+;birdstep.max_links = -1
+
+[Interbase]
+; Allow or prevent persistent links.
+ibase.allow_persistent = 1
+
+; Maximum number of persistent links.  -1 means no limit.
+ibase.max_persistent = -1
+
+; Maximum number of links (persistent + non-persistent).  -1 means no limit.
+ibase.max_links = -1
+
+; Default database name for ibase_connect().
+;ibase.default_db =
+
+; Default username for ibase_connect().
+;ibase.default_user =
+
+; Default password for ibase_connect().
+;ibase.default_password =
+
+; Default charset for ibase_connect().
+;ibase.default_charset =
+
+; Default timestamp format.
+ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
+
+; Default date format.
+ibase.dateformat = "%Y-%m-%d"
+
+; Default time format.
+ibase.timeformat = "%H:%M:%S"
+
+[MySQLi]
+
+; Maximum number of persistent links.  -1 means no limit.
+; http://php.net/mysqli.max-persistent
+mysqli.max_persistent = -1
+
+; Allow accessing, from PHP's perspective, local files with LOAD DATA statements
+; http://php.net/mysqli.allow_local_infile
+;mysqli.allow_local_infile = On
+
+; Allow or prevent persistent links.
+; http://php.net/mysqli.allow-persistent
+mysqli.allow_persistent = On
+
+; Maximum number of links.  -1 means no limit.
+; http://php.net/mysqli.max-links
+mysqli.max_links = -1
+
+; If mysqlnd is used: Number of cache slots for the internal result set cache
+; http://php.net/mysqli.cache_size
+mysqli.cache_size = 2000
+
+; Default port number for mysqli_connect().  If unset, mysqli_connect() will use
+; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the
+; compile-time value defined MYSQL_PORT (in that order).  Win32 will only look
+; at MYSQL_PORT.
+; http://php.net/mysqli.default-port
+mysqli.default_port = 3306
+
+; Default socket name for local MySQL connects.  If empty, uses the built-in
+; MySQL defaults.
+; http://php.net/mysqli.default-socket
+mysqli.default_socket =
+
+; Default host for mysql_connect() (doesn't apply in safe mode).
+; http://php.net/mysqli.default-host
+mysqli.default_host =
+
+; Default user for mysql_connect() (doesn't apply in safe mode).
+; http://php.net/mysqli.default-user
+mysqli.default_user =
+
+; Default password for mysqli_connect() (doesn't apply in safe mode).
+; Note that this is generally a *bad* idea to store passwords in this file.
+; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw")
+; and reveal this password!  And of course, any users with read access to this
+; file will be able to reveal the password as well.
+; http://php.net/mysqli.default-pw
+mysqli.default_pw =
+
+; Allow or prevent reconnect
+mysqli.reconnect = Off
+
+[mysqlnd]
+; Enable / Disable collection of general statistics by mysqlnd which can be
+; used to tune and monitor MySQL operations.
+; http://php.net/mysqlnd.collect_statistics
+mysqlnd.collect_statistics = On
+
+; Enable / Disable collection of memory usage statistics by mysqlnd which can be
+; used to tune and monitor MySQL operations.
+; http://php.net/mysqlnd.collect_memory_statistics
+mysqlnd.collect_memory_statistics = On
+
+; Records communication from all extensions using mysqlnd to the specified log
+; file.
+; http://php.net/mysqlnd.debug
+;mysqlnd.debug =
+
+; Defines which queries will be logged.
+; http://php.net/mysqlnd.log_mask
+;mysqlnd.log_mask = 0
+
+; Default size of the mysqlnd memory pool, which is used by result sets.
+; http://php.net/mysqlnd.mempool_default_size
+;mysqlnd.mempool_default_size = 16000
+
+; Size of a pre-allocated buffer used when sending commands to MySQL in bytes.
+; http://php.net/mysqlnd.net_cmd_buffer_size
+;mysqlnd.net_cmd_buffer_size = 2048
+
+; Size of a pre-allocated buffer used for reading data sent by the server in
+; bytes.
+; http://php.net/mysqlnd.net_read_buffer_size
+;mysqlnd.net_read_buffer_size = 32768
+
+; Timeout for network requests in seconds.
+; http://php.net/mysqlnd.net_read_timeout
+;mysqlnd.net_read_timeout = 31536000
+
+; SHA-256 Authentication Plugin related. File with the MySQL server public RSA
+; key.
+; http://php.net/mysqlnd.sha256_server_public_key
+;mysqlnd.sha256_server_public_key =
+
+[OCI8]
+
+; Connection: Enables privileged connections using external
+; credentials (OCI_SYSOPER, OCI_SYSDBA)
+; http://php.net/oci8.privileged-connect
+;oci8.privileged_connect = Off
+
+; Connection: The maximum number of persistent OCI8 connections per
+; process. Using -1 means no limit.
+; http://php.net/oci8.max-persistent
+;oci8.max_persistent = -1
+
+; Connection: The maximum number of seconds a process is allowed to
+; maintain an idle persistent connection. Using -1 means idle
+; persistent connections will be maintained forever.
+; http://php.net/oci8.persistent-timeout
+;oci8.persistent_timeout = -1
+
+; Connection: The number of seconds that must pass before issuing a
+; ping during oci_pconnect() to check the connection validity. When
+; set to 0, each oci_pconnect() will cause a ping. Using -1 disables
+; pings completely.
+; http://php.net/oci8.ping-interval
+;oci8.ping_interval = 60
+
+; Connection: Set this to a user chosen connection class to be used
+; for all pooled server requests with Oracle 11g Database Resident
+; Connection Pooling (DRCP).  To use DRCP, this value should be set to
+; the same string for all web servers running the same application,
+; the database pool must be configured, and the connection string must
+; specify to use a pooled server.
+;oci8.connection_class =
+
+; High Availability: Using On lets PHP receive Fast Application
+; Notification (FAN) events generated when a database node fails. The
+; database must also be configured to post FAN events.
+;oci8.events = Off
+
+; Tuning: This option enables statement caching, and specifies how
+; many statements to cache. Using 0 disables statement caching.
+; http://php.net/oci8.statement-cache-size
+;oci8.statement_cache_size = 20
+
+; Tuning: Enables statement prefetching and sets the default number of
+; rows that will be fetched automatically after statement execution.
+; http://php.net/oci8.default-prefetch
+;oci8.default_prefetch = 100
+
+; Compatibility. Using On means oci_close() will not close
+; oci_connect() and oci_new_connect() connections.
+; http://php.net/oci8.old-oci-close-semantics
+;oci8.old_oci_close_semantics = Off
+
+[PostgreSQL]
+; Allow or prevent persistent links.
+; http://php.net/pgsql.allow-persistent
+pgsql.allow_persistent = On
+
+; Detect broken persistent links always with pg_pconnect().
+; Auto reset feature requires a little overheads.
+; http://php.net/pgsql.auto-reset-persistent
+pgsql.auto_reset_persistent = Off
+
+; Maximum number of persistent links.  -1 means no limit.
+; http://php.net/pgsql.max-persistent
+pgsql.max_persistent = -1
+
+; Maximum number of links (persistent+non persistent).  -1 means no limit.
+; http://php.net/pgsql.max-links
+pgsql.max_links = -1
+
+; Ignore PostgreSQL backends Notice message or not.
+; Notice message logging require a little overheads.
+; http://php.net/pgsql.ignore-notice
+pgsql.ignore_notice = 0
+
+; Log PostgreSQL backends Notice message or not.
+; Unless pgsql.ignore_notice=0, module cannot log notice message.
+; http://php.net/pgsql.log-notice
+pgsql.log_notice = 0
+
+[bcmath]
+; Number of decimal digits for all bcmath functions.
+; http://php.net/bcmath.scale
+bcmath.scale = 0
+
+[browscap]
+; http://php.net/browscap
+;browscap = extra/browscap.ini
+
+[Session]
+; Handler used to store/retrieve data.
+; http://php.net/session.save-handler
+session.save_handler = files
+
+; Argument passed to save_handler.  In the case of files, this is the path
+; where data files are stored. Note: Windows users have to change this
+; variable in order to use PHP's session functions.
+;
+; The path can be defined as:
+;
+;     session.save_path = "N;/path"
+;
+; where N is an integer.  Instead of storing all the session files in
+; /path, what this will do is use subdirectories N-levels deep, and
+; store the session data in those directories.  This is useful if
+; your OS has problems with many files in one directory, and is
+; a more efficient layout for servers that handle many sessions.
+;
+; NOTE 1: PHP will not create this directory structure automatically.
+;         You can use the script in the ext/session dir for that purpose.
+; NOTE 2: See the section on garbage collection below if you choose to
+;         use subdirectories for session storage
+;
+; The file storage module creates files using mode 600 by default.
+; You can change that by using
+;
+;     session.save_path = "N;MODE;/path"
+;
+; where MODE is the octal representation of the mode. Note that this
+; does not overwrite the process's umask.
+; http://php.net/session.save-path
+;session.save_path = "/tmp"
+
+; Whether to use strict session mode.
+; Strict session mode does not accept uninitialized session ID and regenerate
+; session ID if browser sends uninitialized session ID. Strict mode protects
+; applications from session fixation via session adoption vulnerability. It is
+; disabled by default for maximum compatibility, but enabling it is encouraged.
+; https://wiki.php.net/rfc/strict_sessions
+session.use_strict_mode = 0
+
+; Whether to use cookies.
+; http://php.net/session.use-cookies
+session.use_cookies = 1
+
+; http://php.net/session.cookie-secure
+;session.cookie_secure =
+
+; This option forces PHP to fetch and use a cookie for storing and maintaining
+; the session id. We encourage this operation as it's very helpful in combating
+; session hijacking when not specifying and managing your own session id. It is
+; not the be-all and end-all of session hijacking defense, but it's a good start.
+; http://php.net/session.use-only-cookies
+session.use_only_cookies = 1
+
+; Name of the session (used as cookie name).
+; http://php.net/session.name
+session.name = PHPSESSID
+
+; Initialize session on request startup.
+; http://php.net/session.auto-start
+session.auto_start = 0
+
+; Lifetime in seconds of cookie or, if 0, until browser is restarted.
+; http://php.net/session.cookie-lifetime
+session.cookie_lifetime = 0
+
+; The path for which the cookie is valid.
+; http://php.net/session.cookie-path
+session.cookie_path = /
+
+; The domain for which the cookie is valid.
+; http://php.net/session.cookie-domain
+session.cookie_domain =
+
+; Whether or not to add the httpOnly flag to the cookie, which makes it inaccessible to browser scripting languages such as JavaScript.
+; http://php.net/session.cookie-httponly
+session.cookie_httponly =
+
+; Handler used to serialize data.  php is the standard serializer of PHP.
+; http://php.net/session.serialize-handler
+session.serialize_handler = php
+
+; Defines the probability that the 'garbage collection' process is started
+; on every session initialization. The probability is calculated by using
+; gc_probability/gc_divisor. Where session.gc_probability is the numerator
+; and gc_divisor is the denominator in the equation. Setting this value to 1
+; when the session.gc_divisor value is 100 will give you approximately a 1% chance
+; the gc will run on any give request.
+; Default Value: 1
+; Development Value: 1
+; Production Value: 1
+; http://php.net/session.gc-probability
+session.gc_probability = 1
+
+; Defines the probability that the 'garbage collection' process is started on every
+; session initialization. The probability is calculated by using the following equation:
+; gc_probability/gc_divisor. Where session.gc_probability is the numerator and
+; session.gc_divisor is the denominator in the equation. Setting this value to 1
+; when the session.gc_divisor value is 100 will give you approximately a 1% chance
+; the gc will run on any give request. Increasing this value to 1000 will give you
+; a 0.1% chance the gc will run on any give request. For high volume production servers,
+; this is a more efficient approach.
+; Default Value: 100
+; Development Value: 1000
+; Production Value: 1000
+; http://php.net/session.gc-divisor
+session.gc_divisor = 1000
+
+; After this number of seconds, stored data will be seen as 'garbage' and
+; cleaned up by the garbage collection process.
+; http://php.net/session.gc-maxlifetime
+session.gc_maxlifetime = 1440
+
+; NOTE: If you are using the subdirectory option for storing session files
+;       (see session.save_path above), then garbage collection does *not*
+;       happen automatically.  You will need to do your own garbage
+;       collection through a shell script, cron entry, or some other method.
+;       For example, the following script would is the equivalent of
+;       setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes):
+;          find /path/to/sessions -cmin +24 -type f | xargs rm
+
+; Check HTTP Referer to invalidate externally stored URLs containing ids.
+; HTTP_REFERER has to contain this substring for the session to be
+; considered as valid.
+; http://php.net/session.referer-check
+session.referer_check =
+
+; Set to {nocache,private,public,} to determine HTTP caching aspects
+; or leave this empty to avoid sending anti-caching headers.
+; http://php.net/session.cache-limiter
+session.cache_limiter = nocache
+
+; Document expires after n minutes.
+; http://php.net/session.cache-expire
+session.cache_expire = 180
+
+; trans sid support is disabled by default.
+; Use of trans sid may risk your users' security.
+; Use this option with caution.
+; - User may send URL contains active session ID
+;   to other person via. email/irc/etc.
+; - URL that contains active session ID may be stored
+;   in publicly accessible computer.
+; - User may access your site with the same session ID
+;   always using URL stored in browser's history or bookmarks.
+; http://php.net/session.use-trans-sid
+session.use_trans_sid = 0
+
+; Set session ID character length. This value could be between 22 to 256.
+; Shorter length than default is supported only for compatibility reason.
+; Users should use 32 or more chars.
+; http://php.net/session.sid-length
+; Default Value: 32
+; Development Value: 26
+; Production Value: 26
+session.sid_length = 26
+
+; The URL rewriter will look for URLs in a defined set of HTML tags.
+; <form> is special; if you include them here, the rewriter will
+; add a hidden <input> field with the info which is otherwise appended
+; to URLs. <form> tag's action attribute URL will not be modified
+; unless it is specified.
+; Note that all valid entries require a "=", even if no value follows.
+; Default Value: "a=href,area=href,frame=src,form="
+; Development Value: "a=href,area=href,frame=src,form="
+; Production Value: "a=href,area=href,frame=src,form="
+; http://php.net/url-rewriter.tags
+session.trans_sid_tags = "a=href,area=href,frame=src,form="
+
+; URL rewriter does not rewrite absolute URLs by default.
+; To enable rewrites for absolute pathes, target hosts must be specified
+; at RUNTIME. i.e. use ini_set()
+; <form> tags is special. PHP will check action attribute's URL regardless
+; of session.trans_sid_tags setting.
+; If no host is defined, HTTP_HOST will be used for allowed host.
+; Example value: php.net,www.php.net,wiki.php.net
+; Use "," for multiple hosts. No spaces are allowed.
+; Default Value: ""
+; Development Value: ""
+; Production Value: ""
+;session.trans_sid_hosts=""
+
+; Define how many bits are stored in each character when converting
+; the binary hash data to something readable.
+; Possible values:
+;   4  (4 bits: 0-9, a-f)
+;   5  (5 bits: 0-9, a-v)
+;   6  (6 bits: 0-9, a-z, A-Z, "-", ",")
+; Default Value: 4
+; Development Value: 5
+; Production Value: 5
+; http://php.net/session.hash-bits-per-character
+session.sid_bits_per_character = 5
+
+; Enable upload progress tracking in $_SESSION
+; Default Value: On
+; Development Value: On
+; Production Value: On
+; http://php.net/session.upload-progress.enabled
+;session.upload_progress.enabled = On
+
+; Cleanup the progress information as soon as all POST data has been read
+; (i.e. upload completed).
+; Default Value: On
+; Development Value: On
+; Production Value: On
+; http://php.net/session.upload-progress.cleanup
+;session.upload_progress.cleanup = On
+
+; A prefix used for the upload progress key in $_SESSION
+; Default Value: "upload_progress_"
+; Development Value: "upload_progress_"
+; Production Value: "upload_progress_"
+; http://php.net/session.upload-progress.prefix
+;session.upload_progress.prefix = "upload_progress_"
+
+; The index name (concatenated with the prefix) in $_SESSION
+; containing the upload progress information
+; Default Value: "PHP_SESSION_UPLOAD_PROGRESS"
+; Development Value: "PHP_SESSION_UPLOAD_PROGRESS"
+; Production Value: "PHP_SESSION_UPLOAD_PROGRESS"
+; http://php.net/session.upload-progress.name
+;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
+
+; How frequently the upload progress should be updated.
+; Given either in percentages (per-file), or in bytes
+; Default Value: "1%"
+; Development Value: "1%"
+; Production Value: "1%"
+; http://php.net/session.upload-progress.freq
+;session.upload_progress.freq =  "1%"
+
+; The minimum delay between updates, in seconds
+; Default Value: 1
+; Development Value: 1
+; Production Value: 1
+; http://php.net/session.upload-progress.min-freq
+;session.upload_progress.min_freq = "1"
+
+; Only write session data when session data is changed. Enabled by default.
+; http://php.net/session.lazy-write
+;session.lazy_write = On
+
+[Assertion]
+; Switch whether to compile assertions at all (to have no overhead at run-time)
+; -1: Do not compile at all
+;  0: Jump over assertion at run-time
+;  1: Execute assertions
+; Changing from or to a negative value is only possible in php.ini! (For turning assertions on and off at run-time, see assert.active, when zend.assertions = 1)
+; Default Value: 1
+; Development Value: 1
+; Production Value: -1
+; http://php.net/zend.assertions
+zend.assertions = 1
+
+; Assert(expr); active by default.
+; http://php.net/assert.active
+;assert.active = On
+
+; Throw an AssertationException on failed assertions
+; http://php.net/assert.exception
+;assert.exception = On
+
+; Issue a PHP warning for each failed assertion. (Overridden by assert.exception if active)
+; http://php.net/assert.warning
+;assert.warning = On
+
+; Don't bail out by default.
+; http://php.net/assert.bail
+;assert.bail = Off
+
+; User-function to be called if an assertion fails.
+; http://php.net/assert.callback
+;assert.callback = 0
+
+; Eval the expression with current error_reporting().  Set to true if you want
+; error_reporting(0) around the eval().
+; http://php.net/assert.quiet-eval
+;assert.quiet_eval = 0
+
+[COM]
+; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs
+; http://php.net/com.typelib-file
+;com.typelib_file =
+
+; allow Distributed-COM calls
+; http://php.net/com.allow-dcom
+;com.allow_dcom = true
+
+; autoregister constants of a components typlib on com_load()
+; http://php.net/com.autoregister-typelib
+;com.autoregister_typelib = true
+
+; register constants casesensitive
+; http://php.net/com.autoregister-casesensitive
+;com.autoregister_casesensitive = false
+
+; show warnings on duplicate constant registrations
+; http://php.net/com.autoregister-verbose
+;com.autoregister_verbose = true
+
+; The default character set code-page to use when passing strings to and from COM objects.
+; Default: system ANSI code page
+;com.code_page=
+
+[mbstring]
+; language for internal character representation.
+; This affects mb_send_mail() and mbstring.detect_order.
+; http://php.net/mbstring.language
+;mbstring.language = Japanese
+
+; Use of this INI entry is deprecated, use global internal_encoding instead.
+; internal/script encoding.
+; Some encoding cannot work as internal encoding. (e.g. SJIS, BIG5, ISO-2022-*)
+; If empty, default_charset or internal_encoding or iconv.internal_encoding is used.
+; The precedence is: default_charset < internal_encoding < iconv.internal_encoding
+;mbstring.internal_encoding =
+
+; Use of this INI entry is deprecated, use global input_encoding instead.
+; http input encoding.
+; mbstring.encoding_traslation = On is needed to use this setting.
+; If empty, default_charset or input_encoding or mbstring.input is used.
+; The precedence is: default_charset < intput_encoding < mbsting.http_input
+; http://php.net/mbstring.http-input
+;mbstring.http_input =
+
+; Use of this INI entry is deprecated, use global output_encoding instead.
+; http output encoding.
+; mb_output_handler must be registered as output buffer to function.
+; If empty, default_charset or output_encoding or mbstring.http_output is used.
+; The precedence is: default_charset < output_encoding < mbstring.http_output
+; To use an output encoding conversion, mbstring's output handler must be set
+; otherwise output encoding conversion cannot be performed.
+; http://php.net/mbstring.http-output
+;mbstring.http_output =
+
+; enable automatic encoding translation according to
+; mbstring.internal_encoding setting. Input chars are
+; converted to internal encoding by setting this to On.
+; Note: Do _not_ use automatic encoding translation for
+;       portable libs/applications.
+; http://php.net/mbstring.encoding-translation
+;mbstring.encoding_translation = Off
+
+; automatic encoding detection order.
+; "auto" detect order is changed according to mbstring.language
+; http://php.net/mbstring.detect-order
+;mbstring.detect_order = auto
+
+; substitute_character used when character cannot be converted
+; one from another
+; http://php.net/mbstring.substitute-character
+;mbstring.substitute_character = none
+
+; overload(replace) single byte functions by mbstring functions.
+; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(),
+; etc. Possible values are 0,1,2,4 or combination of them.
+; For example, 7 for overload everything.
+; 0: No overload
+; 1: Overload mail() function
+; 2: Overload str*() functions
+; 4: Overload ereg*() functions
+; http://php.net/mbstring.func-overload
+;mbstring.func_overload = 0
+
+; enable strict encoding detection.
+; Default: Off
+;mbstring.strict_detection = On
+
+; This directive specifies the regex pattern of content types for which mb_output_handler()
+; is activated.
+; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml)
+;mbstring.http_output_conv_mimetype=
+
+[gd]
+; Tell the jpeg decode to ignore warnings and try to create
+; a gd image. The warning will then be displayed as notices
+; disabled by default
+; http://php.net/gd.jpeg-ignore-warning
+;gd.jpeg_ignore_warning = 1
+
+[exif]
+; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS.
+; With mbstring support this will automatically be converted into the encoding
+; given by corresponding encode setting. When empty mbstring.internal_encoding
+; is used. For the decode settings you can distinguish between motorola and
+; intel byte order. A decode setting cannot be empty.
+; http://php.net/exif.encode-unicode
+;exif.encode_unicode = ISO-8859-15
+
+; http://php.net/exif.decode-unicode-motorola
+;exif.decode_unicode_motorola = UCS-2BE
+
+; http://php.net/exif.decode-unicode-intel
+;exif.decode_unicode_intel    = UCS-2LE
+
+; http://php.net/exif.encode-jis
+;exif.encode_jis =
+
+; http://php.net/exif.decode-jis-motorola
+;exif.decode_jis_motorola = JIS
+
+; http://php.net/exif.decode-jis-intel
+;exif.decode_jis_intel    = JIS
+
+[Tidy]
+; The path to a default tidy configuration file to use when using tidy
+; http://php.net/tidy.default-config
+;tidy.default_config = /usr/local/lib/php/default.tcfg
+
+; Should tidy clean and repair output automatically?
+; WARNING: Do not use this option if you are generating non-html content
+; such as dynamic images
+; http://php.net/tidy.clean-output
+tidy.clean_output = Off
+
+[soap]
+; Enables or disables WSDL caching feature.
+; http://php.net/soap.wsdl-cache-enabled
+soap.wsdl_cache_enabled=1
+
+; Sets the directory name where SOAP extension will put cache files.
+; http://php.net/soap.wsdl-cache-dir
+soap.wsdl_cache_dir="/tmp"
+
+; (time to live) Sets the number of second while cached file will be used
+; instead of original one.
+; http://php.net/soap.wsdl-cache-ttl
+soap.wsdl_cache_ttl=86400
+
+; Sets the size of the cache limit. (Max. number of WSDL files to cache)
+soap.wsdl_cache_limit = 5
+
+[sysvshm]
+; A default size of the shared memory segment
+;sysvshm.init_mem = 10000
+
+[ldap]
+; Sets the maximum number of open links or -1 for unlimited.
+ldap.max_links = -1
+
+[mcrypt]
+; For more information about mcrypt settings see http://php.net/mcrypt-module-open
+
+; Directory where to load mcrypt algorithms
+; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt)
+;mcrypt.algorithms_dir=
+
+; Directory where to load mcrypt modes
+; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt)
+;mcrypt.modes_dir=
+
+[dba]
+;dba.default_handler=
+
+[opcache]
+; Determines if Zend OPCache is enabled
+;opcache.enable=1
+
+; Determines if Zend OPCache is enabled for the CLI version of PHP
+;opcache.enable_cli=0
+
+; The OPcache shared memory storage size.
+;opcache.memory_consumption=128
+
+; The amount of memory for interned strings in Mbytes.
+;opcache.interned_strings_buffer=8
+
+; The maximum number of keys (scripts) in the OPcache hash table.
+; Only numbers between 200 and 1000000 are allowed.
+;opcache.max_accelerated_files=10000
+
+; The maximum percentage of "wasted" memory until a restart is scheduled.
+;opcache.max_wasted_percentage=5
+
+; When this directive is enabled, the OPcache appends the current working
+; directory to the script key, thus eliminating possible collisions between
+; files with the same name (basename). Disabling the directive improves
+; performance, but may break existing applications.
+;opcache.use_cwd=1
+
+; When disabled, you must reset the OPcache manually or restart the
+; webserver for changes to the filesystem to take effect.
+;opcache.validate_timestamps=1
+
+; How often (in seconds) to check file timestamps for changes to the shared
+; memory storage allocation. ("1" means validate once per second, but only
+; once per request. "0" means always validate)
+;opcache.revalidate_freq=2
+
+; Enables or disables file search in include_path optimization
+;opcache.revalidate_path=0
+
+; If disabled, all PHPDoc comments are dropped from the code to reduce the
+; size of the optimized code.
+;opcache.save_comments=1
+
+; If enabled, a fast shutdown sequence is used for the accelerated code
+; Depending on the used Memory Manager this may cause some incompatibilities.
+;opcache.fast_shutdown=0
+
+; Allow file existence override (file_exists, etc.) performance feature.
+;opcache.enable_file_override=0
+
+; A bitmask, where each bit enables or disables the appropriate OPcache
+; passes
+;opcache.optimization_level=0xffffffff
+
+;opcache.inherited_hack=1
+;opcache.dups_fix=0
+
+; The location of the OPcache blacklist file (wildcards allowed).
+; Each OPcache blacklist file is a text file that holds the names of files
+; that should not be accelerated. The file format is to add each filename
+; to a new line. The filename may be a full path or just a file prefix
+; (i.e., /var/www/x  blacklists all the files and directories in /var/www
+; that start with 'x'). Line starting with a ; are ignored (comments).
+;opcache.blacklist_filename=
+
+; Allows exclusion of large files from being cached. By default all files
+; are cached.
+;opcache.max_file_size=0
+
+; Check the cache checksum each N requests.
+; The default value of "0" means that the checks are disabled.
+;opcache.consistency_checks=0
+
+; How long to wait (in seconds) for a scheduled restart to begin if the cache
+; is not being accessed.
+;opcache.force_restart_timeout=180
+
+; OPcache error_log file name. Empty string assumes "stderr".
+;opcache.error_log=
+
+; All OPcache errors go to the Web server log.
+; By default, only fatal errors (level 0) or errors (level 1) are logged.
+; You can also enable warnings (level 2), info messages (level 3) or
+; debug messages (level 4).
+;opcache.log_verbosity_level=1
+
+; Preferred Shared Memory back-end. Leave empty and let the system decide.
+;opcache.preferred_memory_model=
+
+; Protect the shared memory from unexpected writing during script execution.
+; Useful for internal debugging only.
+;opcache.protect_memory=0
+
+; Allows calling OPcache API functions only from PHP scripts which path is
+; started from specified string. The default "" means no restriction
+;opcache.restrict_api=
+
+; Mapping base of shared memory segments (for Windows only). All the PHP
+; processes have to map shared memory into the same address space. This
+; directive allows to manually fix the "Unable to reattach to base address"
+; errors.
+;opcache.mmap_base=
+
+; Enables and sets the second level cache directory.
+; It should improve performance when SHM memory is full, at server restart or
+; SHM reset. The default "" disables file based caching.
+;opcache.file_cache=
+
+; Enables or disables opcode caching in shared memory.
+;opcache.file_cache_only=0
+
+; Enables or disables checksum validation when script loaded from file cache.
+;opcache.file_cache_consistency_checks=1
+
+; Implies opcache.file_cache_only=1 for a certain process that failed to
+; reattach to the shared memory (for Windows only). Explicitly enabled file
+; cache is required.
+;opcache.file_cache_fallback=1
+
+; Enables or disables copying of PHP code (text segment) into HUGE PAGES.
+; This should improve performance, but requires appropriate OS configuration.
+;opcache.huge_code_pages=0
+
+; Validate cached file permissions.
+;opcache.validate_permission=0
+
+; Prevent name collisions in chroot'ed environment.
+;opcache.validate_root=0
+
+[curl]
+; A default value for the CURLOPT_CAINFO option. This is required to be an
+; absolute path.
+;curl.cainfo =
+
+[openssl]
+; The location of a Certificate Authority (CA) file on the local filesystem
+; to use when verifying the identity of SSL/TLS peers. Most users should
+; not specify a value for this directive as PHP will attempt to use the
+; OS-managed cert stores in its absence. If specified, this value may still
+; be overridden on a per-stream basis via the "cafile" SSL stream context
+; option.
+;openssl.cafile=
+
+; If openssl.cafile is not specified or if the CA file is not found, the
+; directory pointed to by openssl.capath is searched for a suitable
+; certificate. This value must be a correctly hashed certificate directory.
+; Most users should not specify a value for this directive as PHP will
+; attempt to use the OS-managed cert stores in its absence. If specified,
+; this value may still be overridden on a per-stream basis via the "capath"
+; SSL stream context option.
+;openssl.capath=
+
+; Local Variables:
+; tab-width: 4
+; End:
+; extension=test.so
+extension=redis.so
+zend_extension=opcache.so
diff --git a/tutorial/conf/supervisord.conf b/tutorial/conf/supervisord.conf
new file mode 100644
index 00000000000..cd3a1a683fa
--- /dev/null
+++ b/tutorial/conf/supervisord.conf
@@ -0,0 +1,136 @@
+; Sample supervisor config file.
+
+[unix_http_server]
+file=/var/run/supervisor/supervisor.sock   ; (the path to the socket file)
+chmod=0700                 ; sockef file mode (default 0700)
+;chown=nobody:nogroup       ; socket file uid:gid owner
+;username=user              ; (default is no username (open server))
+;password=123               ; (default is no password (open server))
+
+;[inet_http_server]         ; inet (TCP) server disabled by default
+;port=127.0.0.1:9001        ; (ip_address:port specifier, *:port for all iface)
+;username=user              ; (default is no username (open server))
+;password=123               ; (default is no password (open server))
+
+[supervisord]
+logfile=/var/log/supervisor/supervisord.log  ; (main log file;default $CWD/supervisord.log)
+logfile_maxbytes=50MB       ; (max main logfile bytes b4 rotation;default 50MB)
+logfile_backups=10          ; (num of main logfile rotation backups;default 10)
+loglevel=info               ; (log level;default info; others: debug,warn,trace)
+pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
+nodaemon=true               ; (start in foreground if true;default false)
+minfds=1024                 ; (min. avail startup file descriptors;default 1024)
+minprocs=200                ; (min. avail process descriptors;default 200)
+;umask=022                  ; (process file creation umask;default 022)
+;user=chrism                 ; (default is current user, required if root)
+;identifier=supervisor       ; (supervisord identifier, default is 'supervisor')
+;directory=/tmp              ; (default is not to cd during start)
+;nocleanup=true              ; (don't clean up tempfiles at start;default false)
+;childlogdir=/tmp            ; ('AUTO' child log dir, default $TEMP)
+;environment=KEY=value       ; (key value pairs to add to environment)
+;strip_ansi=false            ; (strip ansi escape codes in logs; def. false)
+
+; the below section must remain in the config file for RPC
+; (supervisorctl/web interface) to work, additional interfaces may be
+; added by defining them in separate rpcinterface: sections
+[rpcinterface:supervisor]
+supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
+
+[supervisorctl]
+serverurl=unix:///var/run/supervisor/supervisor.sock ; use a unix:// URL  for a unix socket
+;serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
+;username=chris              ; should be same as http_username if set
+;password=123                ; should be same as http_password if set
+;prompt=mysupervisor         ; cmd line prompt (default "supervisor")
+;history_file=~/.sc_history  ; use readline history if available
+
+; The below sample program section shows all possible program subsection values,
+; create one or more 'real' program: sections to be able to control them under
+; supervisor.
+
+;[program:theprogramname]
+;command=/bin/cat              ; the program (relative uses PATH, can take args)
+;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
+;numprocs=1                    ; number of processes copies to start (def 1)
+;directory=/tmp                ; directory to cwd to before exec (def no cwd)
+;umask=022                     ; umask for process (default None)
+;priority=999                  ; the relative start priority (default 999)
+;autostart=true                ; start at supervisord start (default: true)
+;autorestart=true              ; retstart at unexpected quit (default: true)
+;startsecs=10                  ; number of secs prog must stay running (def. 1)
+;startretries=3                ; max # of serial start failures (default 3)
+;exitcodes=0,2                 ; 'expected' exit codes for process (default 0,2)
+;stopsignal=QUIT               ; signal used to kill process (default TERM)
+;stopwaitsecs=10               ; max num secs to wait b4 SIGKILL (default 10)
+;user=chrism                   ; setuid to this UNIX account to run the program
+;redirect_stderr=true          ; redirect proc stderr to stdout (default false)
+;stdout_logfile=/a/path        ; stdout log path, NONE for none; default AUTO
+;stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
+;stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
+;stdout_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
+;stdout_events_enabled=false   ; emit events on stdout writes (default false)
+;stderr_logfile=/a/path        ; stderr log path, NONE for none; default AUTO
+;stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
+;stderr_logfile_backups=10     ; # of stderr logfile backups (default 10)
+;stderr_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
+;stderr_events_enabled=false   ; emit events on stderr writes (default false)
+;environment=A=1,B=2           ; process environment additions (def no adds)
+;serverurl=AUTO                ; override serverurl computation (childutils)
+
+; The below sample eventlistener section shows all possible
+; eventlistener subsection values, create one or more 'real'
+; eventlistener: sections to be able to handle event notifications
+; sent by supervisor.
+
+;[eventlistener:theeventlistenername]
+;command=/bin/eventlistener    ; the program (relative uses PATH, can take args)
+;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
+;numprocs=1                    ; number of processes copies to start (def 1)
+;events=EVENT                  ; event notif. types to subscribe to (req'd)
+;buffer_size=10                ; event buffer queue size (default 10)
+;directory=/tmp                ; directory to cwd to before exec (def no cwd)
+;umask=022                     ; umask for process (default None)
+;priority=-1                   ; the relative start priority (default -1)
+;autostart=true                ; start at supervisord start (default: true)
+;autorestart=unexpected        ; restart at unexpected quit (default: unexpected)
+;startsecs=10                  ; number of secs prog must stay running (def. 1)
+;startretries=3                ; max # of serial start failures (default 3)
+;exitcodes=0,2                 ; 'expected' exit codes for process (default 0,2)
+;stopsignal=QUIT               ; signal used to kill process (default TERM)
+;stopwaitsecs=10               ; max num secs to wait b4 SIGKILL (default 10)
+;user=chrism                   ; setuid to this UNIX account to run the program
+;redirect_stderr=true          ; redirect proc stderr to stdout (default false)
+;stdout_logfile=/a/path        ; stdout log path, NONE for none; default AUTO
+;stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
+;stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
+;stdout_events_enabled=false   ; emit events on stdout writes (default false)
+;stderr_logfile=/a/path        ; stderr log path, NONE for none; default AUTO
+;stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
+;stderr_logfile_backups        ; # of stderr logfile backups (default 10)
+;stderr_events_enabled=false   ; emit events on stderr writes (default false)
+;environment=A=1,B=2           ; process environment additions
+;serverurl=AUTO                ; override serverurl computation (childutils)
+
+; The below sample group section shows all possible group values,
+; create one or more 'real' group: sections to create "heterogeneous"
+; process groups.
+
+;[group:thegroupname]
+;programs=progname1,progname2  ; each refers to 'x' in [program:x] definitions
+;priority=999                  ; the relative start priority (default 999)
+
+; The [include] section can just contain the "files" setting.  This
+; setting can list multiple files (separated by whitespace or
+; newlines).  It can also contain wildcards.  The filenames are
+; interpreted as relative to this file.  Included files *cannot*
+; include files themselves.
+
+[include]
+files = supervisord.d/*.ini
+
+[supervisord]
+nodaemon=true
+[program:nginx]
+command=/usr/local/nginx/sbin/nginx
+[program:php-fpm]
+command=/usr/local/php7/sbin/php-fpm
\ No newline at end of file
diff --git a/tutorial/conf/www.conf b/tutorial/conf/www.conf
new file mode 100644
index 00000000000..6c1f446fdf4
--- /dev/null
+++ b/tutorial/conf/www.conf
@@ -0,0 +1,420 @@
+; Start a new pool named 'www'.
+; the variable $pool can be used in any directive and will be replaced by the
+; pool name ('www' here)
+[www]
+
+; Per pool prefix
+; It only applies on the following directives:
+; - 'access.log'
+; - 'slowlog'
+; - 'listen' (unixsocket)
+; - 'chroot'
+; - 'chdir'
+; - 'php_values'
+; - 'php_admin_values'
+; When not set, the global prefix (or /usr/local/php7) applies instead.
+; Note: This directive can also be relative to the global prefix.
+; Default Value: none
+;prefix = /path/to/pools/$pool
+
+; Unix user/group of processes
+; Note: The user is mandatory. If the group is not set, the default user's group
+;       will be used.
+user = nobody
+group = nobody
+
+; The address on which to accept FastCGI requests.
+; Valid syntaxes are:
+;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific IPv4 address on
+;                            a specific port;
+;   '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
+;                            a specific port;
+;   'port'                 - to listen on a TCP socket to all addresses
+;                            (IPv6 and IPv4-mapped) on a specific port;
+;   '/path/to/unix/socket' - to listen on a unix socket.
+; Note: This value is mandatory.
+listen = 127.0.0.1:9000
+
+; Set listen(2) backlog.
+; Default Value: 511 (-1 on FreeBSD and OpenBSD)
+;listen.backlog = 511
+
+; Set permissions for unix socket, if one is used. In Linux, read/write
+; permissions must be set in order to allow connections from a web server. Many
+; BSD-derived systems allow connections regardless of permissions.
+; Default Values: user and group are set as the running user
+;                 mode is set to 0660
+;listen.owner = nobody
+;listen.group = nobody
+;listen.mode = 0660
+; When POSIX Access Control Lists are supported you can set them using
+; these options, value is a comma separated list of user/group names.
+; When set, listen.owner and listen.group are ignored
+;listen.acl_users =
+;listen.acl_groups =
+
+; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect.
+; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
+; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
+; must be separated by a comma. If this value is left blank, connections will be
+; accepted from any ip address.
+; Default Value: any
+;listen.allowed_clients = 127.0.0.1
+
+; Specify the nice(2) priority to apply to the pool processes (only if set)
+; The value can vary from -19 (highest priority) to 20 (lower priority)
+; Note: - It will only work if the FPM master process is launched as root
+;       - The pool processes will inherit the master process priority
+;         unless it specified otherwise
+; Default Value: no set
+; process.priority = -19
+
+; Set the process dumpable flag (PR_SET_DUMPABLE prctl) even if the process user
+; or group is differrent than the master process user. It allows to create process
+; core dump and ptrace the process for the pool user.
+; Default Value: no
+; process.dumpable = yes
+
+; Choose how the process manager will control the number of child processes.
+; Possible Values:
+;   static  - a fixed number (pm.max_children) of child processes;
+;   dynamic - the number of child processes are set dynamically based on the
+;             following directives. With this process management, there will be
+;             always at least 1 children.
+;             pm.max_children      - the maximum number of children that can
+;                                    be alive at the same time.
+;             pm.start_servers     - the number of children created on startup.
+;             pm.min_spare_servers - the minimum number of children in 'idle'
+;                                    state (waiting to process). If the number
+;                                    of 'idle' processes is less than this
+;                                    number then some children will be created.
+;             pm.max_spare_servers - the maximum number of children in 'idle'
+;                                    state (waiting to process). If the number
+;                                    of 'idle' processes is greater than this
+;                                    number then some children will be killed.
+;  ondemand - no children are created at startup. Children will be forked when
+;             new requests will connect. The following parameter are used:
+;             pm.max_children           - the maximum number of children that
+;                                         can be alive at the same time.
+;             pm.process_idle_timeout   - The number of seconds after which
+;                                         an idle process will be killed.
+; Note: This value is mandatory.
+; pm = dynamic
+pm = static
+
+; The number of child processes to be created when pm is set to 'static' and the
+; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
+; This value sets the limit on the number of simultaneous requests that will be
+; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
+; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
+; CGI. The below defaults are based on a server without much resources. Don't
+; forget to tweak pm.* to fit your needs.
+; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
+; Note: This value is mandatory.
+pm.max_children = 8
+
+; The number of child processes created on startup.
+; Note: Used only when pm is set to 'dynamic'
+; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
+pm.start_servers = 2
+
+; The desired minimum number of idle server processes.
+; Note: Used only when pm is set to 'dynamic'
+; Note: Mandatory when pm is set to 'dynamic'
+pm.min_spare_servers = 1
+
+; The desired maximum number of idle server processes.
+; Note: Used only when pm is set to 'dynamic'
+; Note: Mandatory when pm is set to 'dynamic'
+pm.max_spare_servers = 3
+
+; The number of seconds after which an idle process will be killed.
+; Note: Used only when pm is set to 'ondemand'
+; Default Value: 10s
+;pm.process_idle_timeout = 10s;
+
+; The number of requests each child process should execute before respawning.
+; This can be useful to work around memory leaks in 3rd party libraries. For
+; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
+; Default Value: 0
+;pm.max_requests = 500
+
+; The URI to view the FPM status page. If this value is not set, no URI will be
+; recognized as a status page. It shows the following informations:
+;   pool                 - the name of the pool;
+;   process manager      - static, dynamic or ondemand;
+;   start time           - the date and time FPM has started;
+;   start since          - number of seconds since FPM has started;
+;   accepted conn        - the number of request accepted by the pool;
+;   listen queue         - the number of request in the queue of pending
+;                          connections (see backlog in listen(2));
+;   max listen queue     - the maximum number of requests in the queue
+;                          of pending connections since FPM has started;
+;   listen queue len     - the size of the socket queue of pending connections;
+;   idle processes       - the number of idle processes;
+;   active processes     - the number of active processes;
+;   total processes      - the number of idle + active processes;
+;   max active processes - the maximum number of active processes since FPM
+;                          has started;
+;   max children reached - number of times, the process limit has been reached,
+;                          when pm tries to start more children (works only for
+;                          pm 'dynamic' and 'ondemand');
+; Value are updated in real time.
+; Example output:
+;   pool:                 www
+;   process manager:      static
+;   start time:           01/Jul/2011:17:53:49 +0200
+;   start since:          62636
+;   accepted conn:        190460
+;   listen queue:         0
+;   max listen queue:     1
+;   listen queue len:     42
+;   idle processes:       4
+;   active processes:     11
+;   total processes:      15
+;   max active processes: 12
+;   max children reached: 0
+;
+; By default the status page output is formatted as text/plain. Passing either
+; 'html', 'xml' or 'json' in the query string will return the corresponding
+; output syntax. Example:
+;   http://www.foo.bar/status
+;   http://www.foo.bar/status?json
+;   http://www.foo.bar/status?html
+;   http://www.foo.bar/status?xml
+;
+; By default the status page only outputs short status. Passing 'full' in the
+; query string will also return status for each pool process.
+; Example:
+;   http://www.foo.bar/status?full
+;   http://www.foo.bar/status?json&full
+;   http://www.foo.bar/status?html&full
+;   http://www.foo.bar/status?xml&full
+; The Full status returns for each process:
+;   pid                  - the PID of the process;
+;   state                - the state of the process (Idle, Running, ...);
+;   start time           - the date and time the process has started;
+;   start since          - the number of seconds since the process has started;
+;   requests             - the number of requests the process has served;
+;   request duration     - the duration in µs of the requests;
+;   request method       - the request method (GET, POST, ...);
+;   request URI          - the request URI with the query string;
+;   content length       - the content length of the request (only with POST);
+;   user                 - the user (PHP_AUTH_USER) (or '-' if not set);
+;   script               - the main script called (or '-' if not set);
+;   last request cpu     - the %cpu the last request consumed
+;                          it's always 0 if the process is not in Idle state
+;                          because CPU calculation is done when the request
+;                          processing has terminated;
+;   last request memory  - the max amount of memory the last request consumed
+;                          it's always 0 if the process is not in Idle state
+;                          because memory calculation is done when the request
+;                          processing has terminated;
+; If the process is in Idle state, then informations are related to the
+; last request the process has served. Otherwise informations are related to
+; the current request being served.
+; Example output:
+;   ************************
+;   pid:                  31330
+;   state:                Running
+;   start time:           01/Jul/2011:17:53:49 +0200
+;   start since:          63087
+;   requests:             12808
+;   request duration:     1250261
+;   request method:       GET
+;   request URI:          /test_mem.php?N=10000
+;   content length:       0
+;   user:                 -
+;   script:               /home/fat/web/docs/php/test_mem.php
+;   last request cpu:     0.00
+;   last request memory:  0
+;
+; Note: There is a real-time FPM status monitoring sample web page available
+;       It's available in: /usr/local/php7/share/php/fpm/status.html
+;
+; Note: The value must start with a leading slash (/). The value can be
+;       anything, but it may not be a good idea to use the .php extension or it
+;       may conflict with a real PHP file.
+; Default Value: not set
+;pm.status_path = /status
+
+; The ping URI to call the monitoring page of FPM. If this value is not set, no
+; URI will be recognized as a ping page. This could be used to test from outside
+; that FPM is alive and responding, or to
+; - create a graph of FPM availability (rrd or such);
+; - remove a server from a group if it is not responding (load balancing);
+; - trigger alerts for the operating team (24/7).
+; Note: The value must start with a leading slash (/). The value can be
+;       anything, but it may not be a good idea to use the .php extension or it
+;       may conflict with a real PHP file.
+; Default Value: not set
+;ping.path = /ping
+
+; This directive may be used to customize the response of a ping request. The
+; response is formatted as text/plain with a 200 response code.
+; Default Value: pong
+;ping.response = pong
+
+; The access log file
+; Default: not set
+;access.log = log/$pool.access.log
+
+; The access log format.
+; The following syntax is allowed
+;  %%: the '%' character
+;  %C: %CPU used by the request
+;      it can accept the following format:
+;      - %{user}C for user CPU only
+;      - %{system}C for system CPU only
+;      - %{total}C  for user + system CPU (default)
+;  %d: time taken to serve the request
+;      it can accept the following format:
+;      - %{seconds}d (default)
+;      - %{miliseconds}d
+;      - %{mili}d
+;      - %{microseconds}d
+;      - %{micro}d
+;  %e: an environment variable (same as $_ENV or $_SERVER)
+;      it must be associated with embraces to specify the name of the env
+;      variable. Some exemples:
+;      - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e
+;      - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e
+;  %f: script filename
+;  %l: content-length of the request (for POST request only)
+;  %m: request method
+;  %M: peak of memory allocated by PHP
+;      it can accept the following format:
+;      - %{bytes}M (default)
+;      - %{kilobytes}M
+;      - %{kilo}M
+;      - %{megabytes}M
+;      - %{mega}M
+;  %n: pool name
+;  %o: output header
+;      it must be associated with embraces to specify the name of the header:
+;      - %{Content-Type}o
+;      - %{X-Powered-By}o
+;      - %{Transfert-Encoding}o
+;      - ....
+;  %p: PID of the child that serviced the request
+;  %P: PID of the parent of the child that serviced the request
+;  %q: the query string
+;  %Q: the '?' character if query string exists
+;  %r: the request URI (without the query string, see %q and %Q)
+;  %R: remote IP address
+;  %s: status (response code)
+;  %t: server time the request was received
+;      it can accept a strftime(3) format:
+;      %d/%b/%Y:%H:%M:%S %z (default)
+;      The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag
+;      e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t
+;  %T: time the log has been written (the request has finished)
+;      it can accept a strftime(3) format:
+;      %d/%b/%Y:%H:%M:%S %z (default)
+;      The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag
+;      e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t
+;  %u: remote user
+;
+; Default: "%R - %u %t \"%m %r\" %s"
+;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
+
+; The log file for slow requests
+; Default Value: not set
+; Note: slowlog is mandatory if request_slowlog_timeout is set
+;slowlog = log/$pool.log.slow
+
+; The timeout for serving a single request after which a PHP backtrace will be
+; dumped to the 'slowlog' file. A value of '0s' means 'off'.
+; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
+; Default Value: 0
+;request_slowlog_timeout = 0
+
+; The timeout for serving a single request after which the worker process will
+; be killed. This option should be used when the 'max_execution_time' ini option
+; does not stop script execution for some reason. A value of '0' means 'off'.
+; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
+; Default Value: 0
+;request_terminate_timeout = 0
+
+; Set open file descriptor rlimit.
+; Default Value: system defined value
+;rlimit_files = 1024
+
+; Set max core size rlimit.
+; Possible Values: 'unlimited' or an integer greater or equal to 0
+; Default Value: system defined value
+;rlimit_core = 0
+
+; Chroot to this directory at the start. This value must be defined as an
+; absolute path. When this value is not set, chroot is not used.
+; Note: you can prefix with '$prefix' to chroot to the pool prefix or one
+; of its subdirectories. If the pool prefix is not set, the global prefix
+; will be used instead.
+; Note: chrooting is a great security feature and should be used whenever
+;       possible. However, all PHP paths will be relative to the chroot
+;       (error_log, sessions.save_path, ...).
+; Default Value: not set
+;chroot =
+
+; Chdir to this directory at the start.
+; Note: relative path can be used.
+; Default Value: current directory or / when chroot
+;chdir = /var/www
+
+; Redirect worker stdout and stderr into main error log. If not set, stdout and
+; stderr will be redirected to /dev/null according to FastCGI specs.
+; Note: on highloaded environement, this can cause some delay in the page
+; process time (several ms).
+; Default Value: no
+;catch_workers_output = yes
+
+; Clear environment in FPM workers
+; Prevents arbitrary environment variables from reaching FPM worker processes
+; by clearing the environment in workers before env vars specified in this
+; pool configuration are added.
+; Setting to "no" will make all environment variables available to PHP code
+; via getenv(), $_ENV and $_SERVER.
+; Default Value: yes
+;clear_env = no
+
+; Limits the extensions of the main script FPM will allow to parse. This can
+; prevent configuration mistakes on the web server side. You should only limit
+; FPM to .php extensions to prevent malicious users to use other extensions to
+; execute php code.
+; Note: set an empty value to allow all extensions.
+; Default Value: .php
+;security.limit_extensions = .php .php3 .php4 .php5 .php7
+
+; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
+; the current environment.
+; Default Value: clean env
+;env[HOSTNAME] = $HOSTNAME
+;env[PATH] = /usr/local/bin:/usr/bin:/bin
+;env[TMP] = /tmp
+;env[TMPDIR] = /tmp
+;env[TEMP] = /tmp
+
+; Additional php.ini defines, specific to this pool of workers. These settings
+; overwrite the values previously defined in the php.ini. The directives are the
+; same as the PHP SAPI:
+;   php_value/php_flag             - you can set classic ini defines which can
+;                                    be overwritten from PHP call 'ini_set'.
+;   php_admin_value/php_admin_flag - these directives won't be overwritten by
+;                                     PHP call 'ini_set'
+; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.
+
+; Defining 'extension' will load the corresponding shared extension from
+; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
+; overwrite previously defined php.ini values, but will append the new value
+; instead.
+
+; Note: path INI options can be relative and will be expanded with the prefix
+; (pool, global or /usr/local/php7)
+
+; Default Value: nothing is defined by default except the values in php.ini and
+;                specified at startup with the -d argument
+;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com
+;php_flag[display_errors] = off
+;php_admin_value[error_log] = /var/log/fpm-php.www.log
+;php_admin_flag[log_errors] = on
+;php_admin_value[memory_limit] = 32M
\ No newline at end of file
diff --git a/tutorial/maketest.sh b/tutorial/maketest.sh
new file mode 100644
index 00000000000..9b2d12f3322
--- /dev/null
+++ b/tutorial/maketest.sh
@@ -0,0 +1,15 @@
+#########################################################################
+# File Name: make.sh
+# Author: ma6174
+# mail: ma6174@163.com
+# Created Time: 四  6/21 16:15:12 2018
+#########################################################################
+#!/bin/bash
+#./configure --enable-debug --prefix=/usr/local/php7 --enable-fpm && make && make install && sudo killall php-fpm&& sudo /usr/local/php7/sbin/php-fpm
+#./configure --prefix=/usr/local/php7 --enable-fpm --enable-coro_http --enable-mysqlnd --enable-zip --with-pdo-mysql --with-openssl=/usr/local/Cellar/openssl/1.0.2o_2/ --enable-maintainer-zts --enable-opcache --with-curl && make && make install && sudo /usr/local/php7/sbin/php-fpm
+#完整版mac
+./configure --prefix=/usr/local/php7 --with-iconv=/usr/local/ --enable-fpm --enable-coro_http --enable-mysqlnd --enable-zip --with-pdo-mysql --with-openssl=/usr/local/Cellar/openssl/1.0.2o_2/ --enable-maintainer-zts --enable-opcache --with-curl --enable-bcmath --enable-calendar --enable-dba --enable-dtrace --enable-exif --enable-ftp --enable-intl --enable-mbregex --enable-mbstring --enable-pcntl --enable-phpdbg --enable-phpdbg-webhelper --enable-shmop --enable-soap --enable-sockets --enable-sysvmsg --enable-sysvsem --enable-sysvshm --enable-wddx --enable-zip --with-bz2 --with-freetype-dir=/usr/local/Cellar/freetype/2.9.1/ --with-gd  --with-icu-dir=/usr/local/Cellar/icu4c/62.1/ --with-jpeg-dir=/usr/local/Cellar/jpeg/9c/ --with-kerberos --with-layout=GNU --with-ldap --with-ldap-sasl --with-libedit --with-libzip --with-mcrypt=/usr/local/Cellar/mcrypt/2.6.8/ --with-mhash --with-mysql-sockunixunix=/tmp/mysql.sock --with-mysqli=mysqlnd --with-ndbm --with-pdo-dblib=/usr/local/Cellar/freetds/1.00.92/ --with-pdo-mysql=mysqlnd --with-pdo-odbc=unixODBC,/usr/local/Cellar/unixodbc/2.3.6/ --with-pdo-pgsql=/usr/local/Cellar/libpq/10.4/ --with-pgsql=/usr/local/Cellar/libpq/10.4/ --with-pic --with-png-dir=/usr/local/Cellar/libpng/1.6.34/ --with-pspell=/usr/local/Cellar/aspell/0.60.6.1_1/ --with-unixODBC=/usr/local/Cellar/unixodbc/2.3.6/ --with-webp-dir=/usr/local/Cellar/webp/1.0.0/ --with-xmlrpc --with-xsl --with-zlib && make && make install && sudo /usr/local/php7/sbin/php-fpm
+#完整版docker
+./configure --prefix=/usr/local/php7  --enable-fpm --enable-coro_http --enable-mysqlnd --enable-zip --with-pdo-mysql --with-openssl --enable-maintainer-zts --enable-opcache --with-curl --enable-bcmath --enable-calendar  --enable-dtrace --enable-exif --enable-ftp  --enable-mbregex --enable-mbstring --enable-pcntl --enable-phpdbg --enable-phpdbg-webhelper --enable-shmop --enable-soap --enable-sockets --enable-sysvmsg --enable-sysvsem --enable-sysvshm --enable-wddx  --with-bz2 --with-iconv --with-pic --with-xmlrpc  --with-mhash --with-mysql-sockunixunix=/tmp/mysql.sock --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-kerberos --with-layout=GNU   --with-mcrypt=/usr/include --with-gd --with-jpeg-dir=/usr/include --with-png-dir=/usr/include  --with-webp-dir=/usr/include --with-freetype-dir=/usr/include --with-icu-dir=/usr --with-pspell --with-xsl --with-libzip=/usr/local --enable-zip --with-zlib --with-pdo-dblib --with-pdo-odbc=unixODBC,/usr --with-unixODBC=/usr --with-libedit --enable-dba --with-ldap --with-ldap-sasl --with-pdo-pgsql --with-pgsql --with-gdbm --enable-intl --with-gettext && make && make install
+#./configure --enable-debug --prefix=/usr/local/php7 --enable-fpm && make && make install && sudo gdb /usr/local/php7/sbin/php-fpm
+#./configure CFLAGS="-ggdb3" CXXFLAGS="-ggdb3" --prefix=/usr/local/php7 --enable-fpm --enable-coro_http --with-openssl --enable-maintainer-zts && make && make install && sudo gdb /usr/local/php7/sbin/php-fpm
diff --git a/tutorial/pic/coroutine.jpg b/tutorial/pic/coroutine.jpg
new file mode 100644
index 00000000000..2d9a86f5477
Binary files /dev/null and b/tutorial/pic/coroutine.jpg differ
diff --git a/tutorial/pic/curl.png b/tutorial/pic/curl.png
new file mode 100644
index 00000000000..930600fce35
Binary files /dev/null and b/tutorial/pic/curl.png differ
diff --git a/tutorial/pic/rt.png b/tutorial/pic/rt.png
new file mode 100644
index 00000000000..758a790486e
Binary files /dev/null and b/tutorial/pic/rt.png differ
diff --git a/tutorial/pic/top1.png b/tutorial/pic/top1.png
new file mode 100644
index 00000000000..1a02fe20d17
Binary files /dev/null and b/tutorial/pic/top1.png differ
diff --git a/tutorial/pic/top2.png b/tutorial/pic/top2.png
new file mode 100644
index 00000000000..5516e378c3f
Binary files /dev/null and b/tutorial/pic/top2.png differ
diff --git a/tutorial/run.sh b/tutorial/run.sh
new file mode 100644
index 00000000000..5c80215279e
--- /dev/null
+++ b/tutorial/run.sh
@@ -0,0 +1,208 @@
+mkdir -p /data/soft/
+mkdir -p /data/www/
+
+yum -y install git
+yum -y install autoconf
+yum -y install automake
+yum -y install libtool
+yum -y install make
+yum -y install bison
+yum -y install python-devel
+yum -y install openssl
+yum -y install openssl-devel 
+yum -y install wget
+yum -y install freetype-devel
+yum -y install libjpeg-devel
+yum -y install unixODBC-devel
+yum -y install libpng-devel
+yum -y install aspell-devel
+yum -y install libwebp-devel
+yum -y install systemtap-sdt-devel
+yum -y install bzip2 bzip2-devel
+yum -y install curl-devel
+yum -y install gdbm-devel
+yum -y install libicu-devel
+yum -y install openldap-devel
+
+yum -y install libxslt libxslt-devel
+yum -y install libedit-devel
+yum -y install postgresql-devel
+yum -y install gcc gcc-c++
+yum -y install libxml2-devel
+
+#安装yum扩展包
+yum -y install epel-release
+#yum -y update
+
+yum -y install libmcrypt-devel
+yum -y install gettext-devel
+yum -y install supervisor
+
+
+cd /data/soft/ && wget http://ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-stable.tgz
+cd /data/soft/ && tar zxvf freetds-stable.tgz
+cd /data/soft/freetds-* && ./configure --prefix=/usr --sysconfdir=/etc --with-tdsver=0.91 --enable-msdblib && make && make install
+
+cd /data/soft/ && wget http://nih.at/libzip/libzip-1.2.0.tar.gz
+cd /data/soft/ && tar zxvf libzip-1.2.0.tar.gz && cd libzip-1.2.0 && ./configure --prefix=/usr/local && make && make install
+
+
+
+cp /usr/local/lib/libzip/include/zipconf.h /usr/local/include/zipconf.h
+ln -s /usr/lib64/libldap.so /usr/lib/libldap.so
+ln -s /usr/lib64/liblber* /usr/lib/
+ln -s /usr/lib64/libz* /usr/lib/
+
+
+cd /data/soft/ && wget https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/libevent-2.1.8-stable.tar.gz
+cd /data/soft/ && tar zxvf libevent-2.1.8-stable.tar.gz
+cd /data/soft/libevent-2.1.8-stable && ./configure && make && make install
+
+
+cd /data/soft/ && wget http://nginx.org/download/nginx-1.14.0.tar.gz
+cd /data/soft/ && tar zxf nginx-1.14.0.tar.gz
+
+echo '/usr/local/lib64\
+/usr/local/lib\
+/usr/lib\
+/usr/lib64'>>/etc/ld.so.conf&&ldconfig -v
+
+cd /data/soft/php-coroutine-engine && sh buildconf --force && ./configure --prefix=/usr/local/php7  --enable-fpm --enable-coro_http --enable-mysqlnd --enable-zip --with-pdo-mysql --with-openssl --enable-maintainer-zts --enable-opcache --with-curl --enable-bcmath --enable-calendar  --enable-dtrace --enable-exif --enable-ftp  --enable-mbregex --enable-mbstring --enable-pcntl --enable-phpdbg --enable-phpdbg-webhelper --enable-shmop --enable-soap --enable-sockets --enable-sysvmsg --enable-sysvsem --enable-sysvshm --enable-wddx  --with-bz2 --with-iconv --with-pic --with-xmlrpc  --with-mhash --with-mysql-sockunixunix=/tmp/mysql.sock --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-kerberos --with-layout=GNU   --with-mcrypt=/usr/include --with-gd --with-jpeg-dir=/usr/include --with-png-dir=/usr/include  --with-webp-dir=/usr/include --with-freetype-dir=/usr/include --with-icu-dir=/usr --with-pspell --with-xsl --with-libzip=/usr/local --enable-zip --with-zlib --with-pdo-dblib --with-pdo-odbc=unixODBC,/usr --with-unixODBC=/usr --with-libedit --enable-dba --with-ldap --with-ldap-sasl --with-pdo-pgsql --with-pgsql --with-gdbm --enable-intl --with-gettext && make && make install
+
+#/usr/local/php7/bin/pecl install redis-3.1.2
+#if you need redis 4.1.1 then use this
+/usr/local/php7/bin/pecl install redis
+
+cd /data/soft/nginx-1.14.0 && ./configure && make && make install
+
+cd /data/soft/php-coroutine-engine
+cp ./tutorial/conf/nginx.conf /usr/local/nginx/conf/
+cp ./tutorial/conf/www.conf /usr/local/php7/etc/php-fpm.d/
+cp ./tutorial/conf/php-fpm.conf /usr/local/php7/etc/
+cp ./tutorial/conf/php.ini /usr/local/php7/etc/
+cp ./tutorial/conf/supervisord.conf /etc/supervisord.conf
+
+
+#remove soft 备份
+# mkdir -p /data/soft/soft
+# cd /data/soft
+# cp /usr/lib64/libcrypt.so.1 soft
+# cp /usr/local/lib/libzip.so.5 soft
+# cp /usr/lib64/libz.so.1 soft
+# cp /usr/lib64/libexslt.so.0 soft
+# cp /usr/lib64/libresolv.so.2 soft
+# cp /usr/lib64/libedit.so.0 soft
+# cp /usr/lib64/libncurses.so.5 soft
+# cp /usr/lib64/libtinfo.so.5 soft
+# cp /usr/lib64/libaspell.so.15 soft
+# cp /usr/lib64/libpspell.so.15 soft
+# cp /usr/lib64/libpq.so.5 soft
+# cp /usr/lib64/librt.so.1 soft
+# cp /lib/libsybdb.so.5 soft
+# cp /usr/lib64/libmcrypt.so.4 soft
+# cp /usr/lib64/libldap-2.4.so.2 soft
+# cp /usr/lib64/liblber-2.4.so.2 soft
+# cp /usr/lib64/libstdc++.so.6 soft
+# cp /usr/lib64/libpng15.so.15 soft
+# cp /usr/lib64/libjpeg.so.62 soft
+# cp /usr/lib64/libwebp.so.4 soft
+# cp /usr/lib64/libgdbm.so.4 soft
+# cp /usr/lib64/libcurl.so.4 soft
+# cp /usr/lib64/libbz2.so.1 soft
+# cp /usr/lib64/libm.so.6 soft
+# cp /usr/lib64/libdl.so.2 soft
+# cp /usr/lib64/libnsl.so.1 soft
+# cp /usr/lib64/libpthread.so.0 soft
+# cp /usr/lib64/libxml2.so.2 soft
+# cp /usr/lib64/libgssapi_krb5.so.2 soft
+# cp /usr/lib64/libkrb5.so.3 soft
+# cp /usr/lib64/libk5crypto.so.3 soft
+# cp /usr/lib64/libcom_err.so.2 soft
+# cp /usr/lib64/libssl.so.10 soft
+# cp /usr/lib64/libcrypto.so.10 soft
+# cp /usr/lib64/libfreetype.so.6 soft
+# cp /usr/lib64/libicui18n.so.50 soft
+# cp /usr/lib64/libicuuc.so.50 soft
+# cp /usr/lib64/libicudata.so.50 soft
+# cp /usr/lib64/libicuio.so.50 soft
+# cp /usr/lib64/libodbc.so.2 soft
+# cp /usr/lib64/libxslt.so.1 soft
+# cp /usr/local/lib/libevent-2.1.so.6 soft
+# cp /usr/lib64/libgcc_s.so.1 soft
+# cp /usr/lib64/libc.so.6 soft
+# cp /lib64/ld-linux-x86-64.so.2 soft
+# cp /usr/lib64/libfreebl3.so soft
+# cp /usr/lib64/libgcrypt.so.11 soft
+# cp /usr/lib64/libgpg-error.so.0 soft
+# cp /usr/lib64/libldap_r-2.4.so.2 soft
+# cp /usr/lib64/libsasl2.so.3 soft
+# cp /usr/lib64/libssl3.so soft
+# cp /usr/lib64/libsmime3.so soft
+# cp /usr/lib64/libnss3.so soft
+# cp /usr/lib64/libnssutil3.so soft
+# cp /usr/lib64/libplds4.so soft
+# cp /usr/lib64/libplc4.so soft
+# cp /usr/lib64/libnspr4.so soft
+# cp /usr/lib64/libidn.so.11 soft
+# cp /usr/lib64/libssh2.so.1 soft
+# cp /usr/lib64/liblzma.so.5 soft
+# cp /usr/lib64/libkrb5support.so.0 soft
+# cp /usr/lib64/libkeyutils.so.1 soft
+# cp /usr/lib64/libltdl.so.7 soft
+# cp /usr/lib64/libselinux.so.1 soft
+# cp /usr/lib64/libpcre.so.1 soft
+
+
+# yum -y remove git
+# yum -y remove autoconf
+# yum -y remove automake
+# yum -y remove libtool
+# yum -y remove make
+# yum -y remove bison
+# yum -y remove python-devel
+# yum -y remove openssl
+# yum -y remove openssl-devel
+# yum -y remove wget
+# yum -y remove freetype-devel
+# yum -y remove libjpeg-devel
+# yum -y remove unixODBC-devel
+# yum -y remove libpng-devel
+# yum -y remove aspell-devel
+# yum -y remove libwebp-devel
+# yum -y remove systemtap-sdt-devel
+# yum -y remove bzip2 bzip2-devel
+# yum -y remove curl-devel
+# yum -y remove gdbm-devel
+# yum -y remove libicu-devel
+# yum -y remove openldap-devel
+
+# yum -y remove libxslt libxslt-devel
+# yum -y remove libedit-devel
+# yum -y remove postgresql-devel
+# yum -y remove gcc gcc-c++
+# yum -y remove libxml2-devel
+# yum -y remove epel-release
+
+# yum -y remove libmcrypt-devel
+# yum -y remove gettext-devel
+
+# cd /data/soft/freetds-* && make distclean
+# cd /data/soft/libzip-1.2.0 && make distclean
+
+# cd /data/soft/libevent-2.1.8-stable && make distclean
+
+# cd /data/soft
+# #恢复
+# mv soft/libzip.so.5  /usr/local/lib/libzip.so.5
+# mv soft/libsybdb.so.5 /lib/libsybdb.so.5
+# mv soft/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
+# mv soft/libevent-2.1.so.6 /usr/local/lib/libevent-2.1.so.6
+# cp soft/* /usr/lib64
+
+cd /
+rm -rf /data/soft
+
+
+
+
+
diff --git a/tutorial/runAlpine.sh b/tutorial/runAlpine.sh
new file mode 100644
index 00000000000..52abbd63650
--- /dev/null
+++ b/tutorial/runAlpine.sh
@@ -0,0 +1,116 @@
+mkdir -p /data/soft/
+mkdir -p /data/www/
+
+apk add git
+apk add autoconf
+apk add automake
+apk add libtool
+apk add make
+apk add bison
+apk add python-dev
+apk add wget
+apk add freetype-dev
+apk add libjpeg-turbo-dev
+apk add unixodbc-dev
+apk add libpng-dev
+apk add aspell-dev
+apk add libwebp-dev
+        # apk add systemtap-sdt-dev
+apk add bzip2 bzip2-dev
+apk add curl-dev
+apk add gdbm-dev
+apk add icu-dev
+apk add openldap-dev
+
+apk add libxslt libxslt-dev
+apk add libedit-dev
+apk add postgresql-dev
+apk add gcc g++
+apk add libxml2-dev
+
+#安装yum扩展包
+# apk add epel-release
+#yum -y update
+
+apk add libmcrypt-dev
+apk add gettext-dev
+apk add supervisor
+
+# cd /data/soft/ && wget https://github.com/phpce/systemtap/archive/master.zip
+# cd /data/soft/ && unzip master.zip
+# cd /data/soft/ &&wget https://sourceware.org/elfutils/ftp/0.170/elfutils-0.170.tar.bz2
+# cd /data/soft/ &&tar xf elfutils-0.170.tar.bz2
+
+# # cd /data/soft/ && wget https://github.com/phpce/elfutils/archive/master.zip
+# # cd /data/soft/ && unzip master.zip.1
+# cd /data/soft/ && wget https://sourceware.org/systemtap/ftp/releases/systemtap-3.1.tar.gz
+# cd /data/soft/ && tar zxf systemtap-3.1.tar.gz
+# cd systemtap-3.1
+# ./configure --prefix=/opt/stap --disable-docs \
+#     --disable-publican --disable-refdocs CFLAGS="-g -O2" \
+#     --with-elfutils=../elfutils-0.170
+# make -j$(getconf _NPROCESSORS_ONLN) && sudo make install
+
+# export STAP_HOME=/opt/stap/
+
+# export PATH=$STAP_HOME:$PATH
+
+# stap -V
+
+
+# apk add elfutils-dev
+# apk add elfutils-libelf
+# apk add libdw-dev
+# cd /data/soft/systemtap-master/ && 
+
+
+# cd /data/soft/ && wget http://ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-stable.tgz
+# cd /data/soft/ && tar zxvf freetds-stable.tgz
+# cd /data/soft/freetds-* && ./configure --prefix=/usr --sysconfdir=/etc --with-tdsver=0.91 --enable-msdblib && make && make install
+
+apk add freetds-dev
+
+apk add libzip-dev
+
+# cd /data/soft/ && wget http://nih.at/libzip/libzip-1.2.0.tar.gz
+# cd /data/soft/ && tar zxvf libzip-1.2.0.tar.gz && cd libzip-1.2.0 && ./configure --prefix=/usr/local && make && make install
+
+
+
+# cp /usr/local/lib/libzip/include/zipconf.h /usr/local/include/zipconf.h
+# ln -s /usr/lib64/libldap.so /usr/lib/libldap.so
+# ln -s /usr/lib64/liblber* /usr/lib/
+# ln -s /usr/lib64/libz* /usr/lib/
+
+apk add libevent
+# cd /data/soft/ && wget https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/libevent-2.1.8-stable.tar.gz
+# cd /data/soft/ && tar zxvf libevent-2.1.8-stable.tar.gz
+# cd /data/soft/libevent-2.1.8-stable && ./configure && make && make install
+
+apk add nginx
+# cd /data/soft/ && wget http://nginx.org/download/nginx-1.14.0.tar.gz
+# cd /data/soft/ && tar zxf nginx-1.14.0.tar.gz
+
+# echo '/usr/local/lib64\
+# /usr/local/lib\
+# /usr/lib\
+# /usr/lib64'>>/etc/ld.so.conf&&ldconfig -v
+
+cd /data/soft/php-coroutine-engine && sh buildconf --force && ./configure --prefix=/usr/local/php7  --enable-fpm --enable-coro_http --enable-mysqlnd --enable-zip --with-pdo-mysql --with-openssl --enable-maintainer-zts --enable-opcache --with-curl --enable-bcmath --enable-calendar --enable-exif --enable-ftp  --enable-mbregex --enable-mbstring --enable-pcntl --enable-phpdbg --enable-phpdbg-webhelper --enable-shmop --enable-soap --enable-sockets --enable-sysvmsg --enable-sysvsem --enable-sysvshm --enable-wddx  --with-bz2 --with-iconv --with-pic --with-xmlrpc  --with-mhash --with-mysql-sockunixunix=/tmp/mysql.sock --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-kerberos --with-layout=GNU   --with-mcrypt=/usr/include --with-gd --with-jpeg-dir=/usr/include --with-png-dir=/usr/include  --with-webp-dir=/usr/include --with-freetype-dir=/usr/include --with-icu-dir=/usr --with-pspell --with-xsl --with-libzip=/usr/local --enable-zip --with-zlib --with-pdo-dblib --with-pdo-odbc=unixODBC,/usr --with-unixODBC=/usr --with-libedit --enable-dba --with-ldap --with-ldap-sasl --with-pdo-pgsql --with-pgsql --with-gdbm --enable-intl --with-gettext && make && make install
+
+#/usr/local/php7/bin/pecl install redis-3.1.2
+#if you need redis 4.1.1 then use this
+/usr/local/php7/bin/pecl install redis
+
+# cd /data/soft/nginx-1.14.0 && ./configure && make && make install
+mpdir -p /usr/local/nginx/sbin
+ln -s /usr/sbin/nginx /usr/local/nginx/sbin/nginx
+
+cd /data/soft/php-coroutine-engine
+cp ./tutorial/conf/nginx.conf /etc/nginx/conf/
+cp ./tutorial/conf/www.conf /usr/local/php7/etc/php-fpm.d/
+cp ./tutorial/conf/php-fpm.conf /usr/local/php7/etc/
+cp ./tutorial/conf/php.ini /usr/local/php7/etc/
+cp ./tutorial/conf/supervisord.conf /etc/supervisord.conf
+cd /
+rm -rf /data/soft
diff --git a/tutorial/test.js b/tutorial/test.js
new file mode 100644
index 00000000000..2552904f834
--- /dev/null
+++ b/tutorial/test.js
@@ -0,0 +1,17 @@
+//引入http模块
+var http = require("http");
+//设置主机名
+var hostName = '0.0.0.0';
+//设置端口
+var port = 8080;
+//创建服务
+var server = http.createServer(function(req,res){
+    res.setHeader('Content-Type','text/plain');
+	setTimeout(function(){
+    	res.end("hello nodejs");
+	},2000);
+
+});
+server.listen(port,hostName,function(){
+    console.log(`服务器运行在http://${hostName}:${port}`);
+});
diff --git a/tutorial/test.php b/tutorial/test.php
new file mode 100644
index 00000000000..02ce2ebc8c5
--- /dev/null
+++ b/tutorial/test.php
@@ -0,0 +1,13 @@
+<?php
+ // echo "OK了，,ssss";
+echo "context->thread_id:".ce_context_index()."<br/>\n";
+echo "context->fd:".ce_context_fd()."<br/>\n";
+ // echo "<br/>";
+ // var_dump(ce_http_get("http://localhost:8080/"));
+ var_dump(coro_http_get("http://10.60.198.153:8080/"));
+ //var_dump(coro_http_get("http://localhost:8080/"));
+ // var_dump(coro_http_get("http://live.ksmobile.net/base/apiend"));
+ // echo "<br/>";
+ // echo microtime();
+ // echo "<br/>context->thread_id:".ce_context_index()."<br/>\n";
+?>
diff --git a/tutorial/test2.php b/tutorial/test2.php
new file mode 100644
index 00000000000..b0b87c8ee07
--- /dev/null
+++ b/tutorial/test2.php
@@ -0,0 +1,10 @@
+<?php
+echo "hello php coroutine!\n";
+// echo "libevent 终于OK了，,ssss<br/>\n";
+// echo "context->thread_id:".ce_context_index()."<br/>\n";
+// $a = 1;
+// phpinfo();
+
+// $b = array("1","2");
+// var_dump($b);
+?>
diff --git a/tutorial/test3.php b/tutorial/test3.php
new file mode 100644
index 00000000000..aaa97e8db2d
--- /dev/null
+++ b/tutorial/test3.php
@@ -0,0 +1,3 @@
+<?php
+echo json_encode(coro_http_get("http://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su"));
+?>
diff --git a/tutorial/testcurl.php b/tutorial/testcurl.php
new file mode 100644
index 00000000000..d5338b97040
--- /dev/null
+++ b/tutorial/testcurl.php
@@ -0,0 +1,23 @@
+<?php
+$curl = curl_init();
+//设置抓取的url
+curl_setopt($curl, CURLOPT_URL, 'http://localhost:8080/');
+//设置头文件的信息作为数据流输出
+//curl_setopt($curl, CURLOPT_HEADER, 1);
+//设置获取的信息以文件流的形式返回，而不是直接输出。
+curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+//执行命令
+$data = curl_exec($curl);
+//关闭URL请求
+curl_close($curl);
+//显示获得的数据
+
+ echo "OK了，,ssss";
+
+ echo "<br/>";
+
+var_dump($data);
+ echo "<br/>";
+ echo microtime();
+
+?>
