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