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