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 (!($link_pcontest = @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($plink), mysqli_error($plink)); 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 if ($plink = @my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket)) 133 printf("[010] Can connect using the old password, [%d] %s\n", 134 mysqli_connect_errno($link), mysqli_connect_error($link)); 135 136 echo "After second pconnect:"; 137 var_dump(mysqli_get_links_stats()); 138 139 ob_start(); 140 phpinfo(); 141 $phpinfo = strip_tags(ob_get_contents()); 142 ob_end_clean(); 143 $phpinfo = substr($phpinfo, stripos($phpinfo, 'MysqlI Support => enabled'), 500); 144 if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches)) 145 printf("[010] Cannot get # of active persistent links from phpinfo()\n"); 146 147 var_dump(mysqli_get_links_stats()); 148 149 $num_plinks_kill = $matches[1]; 150 $sstats = mysqli_get_links_stats(); 151 if ($sstats['active_plinks'] != $num_plinks_kill) { 152 printf("[010.2] Num of active plinks differ %s %s\n", $sstats['active_plinks'], $num_plinks_kill); 153 } 154 if ($num_plinks_kill > $num_plinks) 155 printf("[011] Expecting Active Persistent Links < %d, got %d\n", $num_plinks, $num_plinks_kill); 156 157 if (!$plink = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket)) 158 printf("[012] Cannot connect using the new password, [%d] %s\n", 159 mysqli_connect_errno(), mysqli_connect_error()); 160 161 if (!$res = mysqli_query($plink, 'SELECT id, label FROM test WHERE id = 1')) 162 printf("[013] Cannot run query on persistent connection of second DB user, [%d] %s\n", 163 mysqli_errno($plink), mysqli_error($plink)); 164 165 if (!$row = mysqli_fetch_assoc($res)) 166 printf("[014] Cannot run fetch result, [%d] %s\n", 167 mysqli_errno($plink), mysqli_error($plink)); 168 mysqli_free_result($res); 169 var_dump($row); 170 171 if ($plink2 = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket)) { 172 printf("[015] Can open more persistent connections than allowed, [%d] %s\n", 173 mysqli_connect_errno(), mysqli_connect_error()); 174 var_dump(mysqli_get_links_stats()); 175 } 176 177 ob_start(); 178 phpinfo(); 179 $phpinfo = strip_tags(ob_get_contents()); 180 ob_end_clean(); 181 $phpinfo = substr($phpinfo, stripos($phpinfo, 'MysqlI Support => enabled'), 500); 182 if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches)) 183 printf("[016] Cannot get # of active persistent links from phpinfo()\n"); 184 185 $num_plinks = $matches[1]; 186 if ($num_plinks > (int)ini_get('mysqli.max_persistent')) 187 printf("[017] mysqli.max_persistent=%d allows %d open connections!\n", ini_get('mysqli.max_persistent'),$num_plinks); 188 189 mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest'); 190 mysqli_query($link, 'DROP USER pcontest'); 191 mysqli_close($link); 192 print "done!"; 193?> 194--CLEAN-- 195<?php 196require_once 'connect.inc'; 197if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) 198 printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); 199 200if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) 201 printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link)); 202 203mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest'); 204mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost'); 205mysqli_query($link, 'DROP USER pcontest@localhost'); 206mysqli_query($link, 'DROP USER pcontest'); 207 208mysqli_close($link); 209?> 210--EXPECT-- 211mysqli_get_links_stats() expects exactly 0 arguments, 1 given 212Before pconnect:array(3) { 213 ["total"]=> 214 int(1) 215 ["active_plinks"]=> 216 int(0) 217 ["cached_plinks"]=> 218 int(0) 219} 220After pconnect:array(3) { 221 ["total"]=> 222 int(2) 223 ["active_plinks"]=> 224 int(1) 225 ["cached_plinks"]=> 226 int(0) 227} 228array(2) { 229 ["id"]=> 230 string(1) "1" 231 ["label"]=> 232 string(1) "a" 233} 234Before second pconnect:array(3) { 235 ["total"]=> 236 int(2) 237 ["active_plinks"]=> 238 int(1) 239 ["cached_plinks"]=> 240 int(0) 241} 242After second pconnect:array(3) { 243 ["total"]=> 244 int(1) 245 ["active_plinks"]=> 246 int(0) 247 ["cached_plinks"]=> 248 int(0) 249} 250array(3) { 251 ["total"]=> 252 int(1) 253 ["active_plinks"]=> 254 int(0) 255 ["cached_plinks"]=> 256 int(0) 257} 258array(2) { 259 ["id"]=> 260 string(1) "1" 261 ["label"]=> 262 string(1) "a" 263} 264[015] Can open more persistent connections than allowed, [0] 265array(3) { 266 ["total"]=> 267 int(3) 268 ["active_plinks"]=> 269 int(2) 270 ["cached_plinks"]=> 271 int(0) 272} 273done! 274