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