mysqli_fork.phpt 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. --TEST--
  2. Forking a child and using the same connection.
  3. --EXTENSIONS--
  4. mysqli
  5. --SKIPIF--
  6. <?php
  7. require_once('skipifconnectfailure.inc');
  8. if (!function_exists('pcntl_fork'))
  9. die("skip Process Control Functions not available");
  10. if (!function_exists('posix_getpid'))
  11. die("skip POSIX functions not available");
  12. require_once('connect.inc');
  13. if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
  14. die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
  15. if (!have_innodb($link))
  16. die(sprintf("skip Needs InnoDB support, [%d] %s", $link->errno, $link->error));
  17. ?>
  18. --FILE--
  19. <?php
  20. require_once("table.inc");
  21. $res = mysqli_query($link, "SELECT 'dumped by the parent' AS message");
  22. $pid = pcntl_fork();
  23. switch ($pid) {
  24. case -1:
  25. printf("[001] Cannot fork child");
  26. break;
  27. case 0:
  28. /* child */
  29. exit(0);
  30. break;
  31. default:
  32. /* parent */
  33. $status = null;
  34. $wait_id = pcntl_waitpid($pid, $status);
  35. if (pcntl_wifexited($status) && (0 != ($tmp = pcntl_wexitstatus($status)))) {
  36. printf("Exit code: %s\n", (pcntl_wifexited($status)) ? pcntl_wexitstatus($status) : 'n/a');
  37. printf("Signal: %s\n", (pcntl_wifsignaled($status)) ? pcntl_wtermsig($status) : 'n/a');
  38. printf("Stopped: %d\n", (pcntl_wifstopped($status)) ? pcntl_wstopsig($status) : 'n/a');
  39. }
  40. var_dump(mysqli_fetch_assoc($res));
  41. mysqli_free_result($res);
  42. break;
  43. }
  44. if (@mysqli_query($link, "SELECT id FROM test WHERE id = 1"))
  45. printf("[003] Expecting error and closed connection, child exit should have closed connection\n");
  46. else if ((($errno = mysqli_errno($link)) == 0) || ('' == ($error = mysqli_error($link))))
  47. printf("[004] Expecting error string and error code from MySQL, got errno = %s/%s, error = %s/%s\n",
  48. gettype($errno), $errno, gettype($error), $error);
  49. mysqli_close($link);
  50. if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
  51. printf("[005] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
  52. $host, $user, $db, $port, $socket);
  53. /* non trivial tests require a message list for parent-child communication */
  54. if (!mysqli_query($link, "DROP TABLE IF EXISTS messages"))
  55. printf("[006] [%d] %s\n", mysqli_error($link), mysqli_errno($link));
  56. if (!mysqli_query($link, "CREATE TABLE messages(
  57. msg_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  58. msg_time TIMESTAMP,
  59. pid INT NOT NULL,
  60. sender ENUM('child', 'parent') NOT NULL,
  61. msg TEXT) ENGINE = InnoDB"))
  62. printf("[007] [%d] %s\n", mysqli_error($link), mysqli_errno($link));
  63. mysqli_autocommit($link, false);
  64. if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id ASC LIMIT 3", MYSQLI_USE_RESULT))
  65. printf("[008] [%d] %s\n", mysqli_error($link), mysqli_errno($link));
  66. $pid = pcntl_fork();
  67. switch ($pid) {
  68. case -1:
  69. printf("[009] Cannot fork child");
  70. break;
  71. case 0:
  72. /* child */
  73. if (!($plink = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) || !mysqli_autocommit($plink, true))
  74. exit(mysqli_errno($plink));
  75. $sql = sprintf("INSERT INTO messages(pid, sender, msg) VALUES (%d, 'child', '%%s')", posix_getpid());
  76. if (!mysqli_query($plink, sprintf($sql, 'start')))
  77. exit(mysqli_errno($plink));
  78. $parent_sql = sprintf("SELECT msg_id, msg_time, msg FROM messages WHERE pid = %d AND sender = 'parent' ORDER BY msg_id DESC LIMIT 1", posix_getppid());
  79. $msg_id = 0;
  80. while ($row = mysqli_fetch_assoc($res)) {
  81. /* send row to parent */
  82. ob_start();
  83. var_dump($row);
  84. $tmp = ob_get_contents();
  85. ob_end_clean();
  86. if (!mysqli_query($plink, sprintf($sql, $tmp)))
  87. exit(mysqli_errno($plink));
  88. /* let the parent reply... */
  89. $start = time();
  90. do {
  91. usleep(100);
  92. if (!$pres = mysqli_query($plink, $parent_sql))
  93. continue;
  94. $tmp = mysqli_fetch_assoc($pres);
  95. mysqli_free_result($pres);
  96. if (!$tmp || $tmp['msg_id'] == $msg_id)
  97. /* no new message */
  98. continue;
  99. if ($tmp['msg'] == 'stop')
  100. break 2;
  101. $msg_id = $tmp['msg_id'];
  102. break;
  103. } while ((time() - $start) < 5);
  104. }
  105. if (!mysqli_query($plink, sprintf($sql, 'stop')) || !mysqli_commit($link))
  106. exit(mysqli_errno($plink));
  107. exit(0);
  108. break;
  109. default:
  110. /* parent */
  111. if (!$plink = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
  112. printf("[010] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
  113. $host, $user, $db, $port, $socket);
  114. $status = null;
  115. $start = time();
  116. $sql = sprintf("SELECT msg_id, msg_time, msg FROM messages WHERE pid = %d AND sender = 'child' ORDER BY msg_id DESC LIMIT 1", $pid);
  117. $parent_sql = sprintf("INSERT INTO messages (pid, sender, msg) VALUES (%d, 'parent', '%%s')", posix_getpid());
  118. $last_msg_id = 0;
  119. $num_rows = 0;
  120. do {
  121. $wait_id = pcntl_waitpid($pid, $status, WNOHANG);
  122. if ($pres = mysqli_query($plink, $sql)) {
  123. $row = mysqli_fetch_assoc($pres);
  124. if ($row && $row['msg_id'] != $last_msg_id) {
  125. $last_msg_id = $row['msg_id'];
  126. switch ($row['msg']) {
  127. case 'start':
  128. break;
  129. case 'stop':
  130. break 2;
  131. default:
  132. /* client has started fetching rows */
  133. $client_row = $row['msg'];
  134. $num_rows++;
  135. if ($num_rows > 3) {
  136. printf("[011] Child has fetched more than three rows!\n");
  137. var_dump($client_row);
  138. if (!mysqli_query($plink, sprintf($parent_sql, 'stop'))) {
  139. printf("[012] Parent cannot inform child\n", mysqli_errno($plink), mysqli_error($plink));
  140. }
  141. break 2;
  142. }
  143. if (!$parent_row = mysqli_fetch_assoc($res)) {
  144. printf("[013] Parent cannot fetch row %d\n", $num_rows, mysqli_errno($link), mysqli_error($link));
  145. if (!mysqli_query($plink, sprintf($parent_sql, 'stop'))) {
  146. printf("[014] Parent cannot inform child\n", mysqli_errno($plink), mysqli_error($plink));
  147. }
  148. break 2;
  149. }
  150. ob_start();
  151. var_dump($parent_row);
  152. $parent_row = ob_get_contents();
  153. ob_end_clean();
  154. if ($parent_row != $client_row) {
  155. printf("[015] Child indicates different results than parent.\n");
  156. var_dump($client_row);
  157. var_dump($parent_row);
  158. if (!mysqli_query($plink, sprintf($parent_sql, 'stop'))) {
  159. printf("[016] Parent cannot inform child\n", mysqli_errno($plink), mysqli_error($plink));
  160. }
  161. break 2;
  162. }
  163. if (!mysqli_query($plink, sprintf($parent_sql, 'continue'))) {
  164. printf("[017] Parent cannot inform child to continue.\n", mysqli_errno($plink), mysqli_error($plink));
  165. }
  166. break;
  167. }
  168. }
  169. mysqli_free_result($pres);
  170. }
  171. usleep(100);
  172. } while (((time() - $start) < 5) && ($num_rows < 3));
  173. mysqli_close($plink);
  174. $wait_id = pcntl_waitpid($pid, $status);
  175. if (pcntl_wifexited($status) && (0 != ($tmp = pcntl_wexitstatus($status)))) {
  176. printf("Exit code: %s\n", (pcntl_wifexited($status)) ? pcntl_wexitstatus($status) : 'n/a');
  177. printf("Signal: %s\n", (pcntl_wifsignaled($status)) ? pcntl_wtermsig($status) : 'n/a');
  178. printf("Stopped: %d\n", (pcntl_wifstopped($status)) ? pcntl_wstopsig($status) : 'n/a');
  179. }
  180. break;
  181. }
  182. mysqli_free_result($res);
  183. mysqli_close($link);
  184. if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
  185. printf("[018] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
  186. $host, $user, $db, $port, $socket);
  187. if (!$res = mysqli_query($link, "SELECT sender, msg FROM messages ORDER BY msg_id ASC"))
  188. printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
  189. while ($row = mysqli_fetch_assoc($res))
  190. printf("%10s %s\n", $row['sender'], substr($row['msg'], 0, 5));
  191. mysqli_free_result($res);
  192. print "done!";
  193. ?>
  194. --CLEAN--
  195. <?php
  196. require_once("connect.inc");
  197. if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
  198. printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
  199. if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
  200. printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
  201. if (!mysqli_query($link, "DROP TABLE IF EXISTS messages"))
  202. printf("[c003] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
  203. mysqli_close($link);
  204. ?>
  205. --EXPECT--
  206. array(1) {
  207. ["message"]=>
  208. string(20) "dumped by the parent"
  209. }
  210. child start
  211. child array
  212. parent conti
  213. child array
  214. parent conti
  215. child array
  216. parent conti
  217. child stop
  218. done!