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