1--TEST-- 2Persistent connections and mysqli.max_links 3--SKIPIF-- 4<?php 5 require_once('skipif.inc'); 6 require_once('skipifconnectfailure.inc'); 7 require_once('table.inc'); 8 9 mysqli_query($link, 'DROP USER pcontest'); 10 mysqli_query($link, 'DROP USER pcontest@localhost'); 11 12 if (!mysqli_query($link, 'CREATE USER pcontest@"%" IDENTIFIED BY "pcontest"') || 13 !mysqli_query($link, 'CREATE USER pcontest@localhost IDENTIFIED BY "pcontest"')) { 14 printf("skip Cannot create second DB user [%d] %s", mysqli_errno($link), mysqli_error($link)); 15 mysqli_close($link); 16 die("skip CREATE USER failed"); 17 } 18 19 // we might be able to specify the host using CURRENT_USER(), but... 20 if (!mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'%%'", $db)) || 21 !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'localhost'", $db))) { 22 printf("skip Cannot GRANT SELECT to second DB user [%d] %s", mysqli_errno($link), mysqli_error($link)); 23 mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest'); 24 mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost'); 25 mysqli_query($link, 'DROP USER pcontest@localhost'); 26 mysqli_query($link, 'DROP USER pcontest'); 27 mysqli_close($link); 28 die("skip GRANT failed"); 29 } 30 31 if (!($link_pcontest = @my_mysqli_connect($host, 'pcontest', 'pcontest', $db, $port, $socket))) { 32 mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest'); 33 mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost'); 34 mysqli_query($link, 'DROP USER pcontest@localhost'); 35 mysqli_query($link, 'DROP USER pcontest'); 36 mysqli_close($link); 37 die("skip CONNECT using new user failed"); 38 } 39 mysqli_close($link); 40?> 41--INI-- 42mysqli.allow_persistent=1 43mysqli.max_persistent=2 44mysqli.rollback_on_cached_plink=1 45--FILE-- 46<?php 47 require_once("connect.inc"); 48 require_once('table.inc'); 49 50 51 if (!mysqli_query($link, 'DROP USER pcontest') || 52 !mysqli_query($link, 'DROP USER pcontest@localhost') || 53 !mysqli_query($link, 'CREATE USER pcontest@"%" IDENTIFIED BY "pcontest"') || 54 !mysqli_query($link, 'CREATE USER pcontest@localhost IDENTIFIED BY "pcontest"') || 55 !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'%%'", $db)) || 56 !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'localhost'", $db))) { 57 printf("[000] Init failed, [%d] %s\n", 58 mysqli_errno($plink), mysqli_error($plink)); 59 } 60 61 try { 62 mysqli_get_links_stats(1); 63 } catch (ArgumentCountError $exception) { 64 echo $exception->getMessage() . "\n"; 65 } 66 67 echo "Before pconnect:"; 68 var_dump(mysqli_get_links_stats()); 69 70 if (!$plink = my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket)) 71 printf("[001] Cannot connect using the second DB user created during SKIPIF, [%d] %s\n", 72 mysqli_connect_errno(), mysqli_connect_error()); 73 74 echo "After pconnect:"; 75 var_dump(mysqli_get_links_stats()); 76 77 ob_start(); 78 phpinfo(); 79 $phpinfo = strip_tags(ob_get_contents()); 80 ob_end_clean(); 81 82 $phpinfo = substr($phpinfo, strpos($phpinfo, 'MysqlI Support => enabled'), 500); 83 if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches)) 84 printf("[002] Cannot get # active persistent links from phpinfo()\n"); 85 $num_plinks = $matches[1]; 86 87 if (!$res = mysqli_query($plink, 'SELECT id, label FROM test WHERE id = 1')) 88 printf("[003] Cannot run query on persistent connection of second DB user, [%d] %s\n", 89 mysqli_errno($plink), mysqli_error($plink)); 90 91 if (!$row = mysqli_fetch_assoc($res)) 92 printf("[004] Cannot run fetch result, [%d] %s\n", 93 mysqli_errno($plink), mysqli_error($plink)); 94 mysqli_free_result($res); 95 var_dump($row); 96 97 // change the password for the second DB user and kill the persistent connection 98 if ((!mysqli_query($link, 'SET PASSWORD FOR pcontest = "newpass"') && 99 !mysqli_query($link, 'SET PASSWORD FOR pcontest = PASSWORD("newpass")'))|| 100 !mysqli_query($link, 'FLUSH PRIVILEGES')) 101 printf("[005] Cannot change PW of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link)); 102 103 // change the password for the second DB user and kill the persistent connection 104 if ((!mysqli_query($link, 'SET PASSWORD FOR pcontest@localhost = "newpass"') && 105 !mysqli_query($link, 'SET PASSWORD FOR pcontest@localhost = PASSWORD("newpass")')) || 106 !mysqli_query($link, 'FLUSH PRIVILEGES')) 107 printf("[006] Cannot change PW of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link)); 108 109 // persistent connections cannot be closed but only be killed 110 $pthread_id = mysqli_thread_id($plink); 111 if (!mysqli_query($link, sprintf('KILL %d', $pthread_id))) 112 printf("[007] Cannot KILL persistent connection of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link)); 113 // give the server a second to really kill the thread 114 sleep(1); 115 116 if (!$res = mysqli_query($link, "SHOW FULL PROCESSLIST")) 117 printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); 118 119 $running_threads = array(); 120 while ($row = mysqli_fetch_assoc($res)) 121 $running_threads[$row['Id']] = $row; 122 mysqli_free_result($res); 123 124 if (isset($running_threads[$pthread_id])) 125 printf("[009] Persistent connection has not been killed\n"); 126 127 echo "Before second pconnect:"; 128 var_dump(mysqli_get_links_stats()); 129 130 // this fails and we have 0 (<= $num_plinks) connections 131 if ($plink = @my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket)) 132 printf("[010] Can connect using the old password, [%d] %s\n", 133 mysqli_connect_errno($link), mysqli_connect_error($link)); 134 135 echo "After second pconnect:"; 136 var_dump(mysqli_get_links_stats()); 137 138 ob_start(); 139 phpinfo(); 140 $phpinfo = strip_tags(ob_get_contents()); 141 ob_end_clean(); 142 $phpinfo = substr($phpinfo, stripos($phpinfo, 'MysqlI Support => enabled'), 500); 143 if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches)) 144 printf("[010] Cannot get # of active persistent links from phpinfo()\n"); 145 146 var_dump(mysqli_get_links_stats()); 147 148 $num_plinks_kill = $matches[1]; 149 $sstats = mysqli_get_links_stats(); 150 if ($sstats['active_plinks'] != $num_plinks_kill) { 151 printf("[010.2] Num of active plinks differ %s %s\n", $sstats['active_plinks'], $num_plinks_kill); 152 } 153 if ($num_plinks_kill > $num_plinks) 154 printf("[011] Expecting Active Persistent Links < %d, got %d\n", $num_plinks, $num_plinks_kill); 155 156 if (!$plink = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket)) 157 printf("[012] Cannot connect using the new password, [%d] %s\n", 158 mysqli_connect_errno(), mysqli_connect_error()); 159 160 if (!$res = mysqli_query($plink, 'SELECT id, label FROM test WHERE id = 1')) 161 printf("[013] Cannot run query on persistent connection of second DB user, [%d] %s\n", 162 mysqli_errno($plink), mysqli_error($plink)); 163 164 if (!$row = mysqli_fetch_assoc($res)) 165 printf("[014] Cannot run fetch result, [%d] %s\n", 166 mysqli_errno($plink), mysqli_error($plink)); 167 mysqli_free_result($res); 168 var_dump($row); 169 170 if ($plink2 = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket)) { 171 printf("[015] Can open more persistent connections than allowed, [%d] %s\n", 172 mysqli_connect_errno(), mysqli_connect_error()); 173 var_dump(mysqli_get_links_stats()); 174 } 175 176 ob_start(); 177 phpinfo(); 178 $phpinfo = strip_tags(ob_get_contents()); 179 ob_end_clean(); 180 $phpinfo = substr($phpinfo, stripos($phpinfo, 'MysqlI Support => enabled'), 500); 181 if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches)) 182 printf("[016] Cannot get # of active persistent links from phpinfo()\n"); 183 184 $num_plinks = $matches[1]; 185 if ($num_plinks > (int)ini_get('mysqli.max_persistent')) 186 printf("[017] mysqli.max_persistent=%d allows %d open connections!\n", ini_get('mysqli.max_persistent'),$num_plinks); 187 188 mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest'); 189 mysqli_query($link, 'DROP USER pcontest'); 190 mysqli_close($link); 191 print "done!"; 192?> 193--CLEAN-- 194<?php 195require_once("connect.inc"); 196if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) 197 printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); 198 199if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) 200 printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link)); 201 202mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest'); 203mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost'); 204mysqli_query($link, 'DROP USER pcontest@localhost'); 205mysqli_query($link, 'DROP USER pcontest'); 206 207mysqli_close($link); 208?> 209--EXPECT-- 210mysqli_get_links_stats() expects exactly 0 arguments, 1 given 211Before pconnect:array(3) { 212 ["total"]=> 213 int(1) 214 ["active_plinks"]=> 215 int(0) 216 ["cached_plinks"]=> 217 int(0) 218} 219After pconnect:array(3) { 220 ["total"]=> 221 int(2) 222 ["active_plinks"]=> 223 int(1) 224 ["cached_plinks"]=> 225 int(0) 226} 227array(2) { 228 ["id"]=> 229 string(1) "1" 230 ["label"]=> 231 string(1) "a" 232} 233Before second pconnect:array(3) { 234 ["total"]=> 235 int(2) 236 ["active_plinks"]=> 237 int(1) 238 ["cached_plinks"]=> 239 int(0) 240} 241After second pconnect:array(3) { 242 ["total"]=> 243 int(1) 244 ["active_plinks"]=> 245 int(0) 246 ["cached_plinks"]=> 247 int(0) 248} 249array(3) { 250 ["total"]=> 251 int(1) 252 ["active_plinks"]=> 253 int(0) 254 ["cached_plinks"]=> 255 int(0) 256} 257array(2) { 258 ["id"]=> 259 string(1) "1" 260 ["label"]=> 261 string(1) "a" 262} 263[015] Can open more persistent connections than allowed, [0] 264array(3) { 265 ["total"]=> 266 int(3) 267 ["active_plinks"]=> 268 int(2) 269 ["cached_plinks"]=> 270 int(0) 271} 272done! 273