ext/mysqli: mysqli double increments num_active_persistent when using real_connect
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- C
- Star
- 40.4k
- Fork
- 8.2k
- Merge trung bình
- 2 ngày 13 giờ
- Pull request đã merge (30 ngày)
- 96
Mô tả
Description
The following code:
<?php
$use_real_connect = true;
$host = "p:localhost";
$user = "root";
$password = "password";
for ($i = 0; $i < 100; $i++)
{
if ($use_real_connect)
{
$mysql = mysqli_init();
mysqli_real_connect($mysql, $host, $user, $password);
}
else
{
$mysql = mysqli_connect($host, $user, $password);
}
mysqli_close($mysql);
}
$stats = mysqli_get_links_stats();
var_dump($stats);
Resulted in this output:
array(3) {
["total"]=>
int(0)
["active_plinks"]=>
int(99)
["cached_plinks"]=>
int(1)
}
But I expected this output instead:
array(3) {
["total"]=>
int(0)
["active_plinks"]=>
int(0)
["cached_plinks"]=>
int(1)
}
The code gives the correct output if you turn off the $use_real_connect flag.
This is caused by the persistent branch of mysqli_common_connect incrementing num_inactive_persistent (mysqli_nonapi.c:179 in tag php-8.5.8) when a persistent connection is reused based on the connection hash, then jumping to the end: label, and incrementing it again under this condition:
// mysqli_nonapi.c:296
if (persistent && (new_connection || is_real_connect)) {
MyG(num_active_persistent)++;
}
Because mysql_close has already been called on the persisted connection, we get a total increase in active persistent connections by 1.
I'm not entirely sure why || is_real_connect is needed in that check, it looks to me like new_connection still covers the persistent case.
EDIT: The consequence of this issue is that if you make a persistent connection a ton of times (say in a long-running php-fpm process), and then make a different connection that doesn't yet exist in the connections hash table, you will always fail with the error Too many open persistent links with a massively huge number of active persistent connections. Note that this does not actually leak connections to the server, you still are capped properly by at most mysqli.max_persistent.
PHP Version
PHP 8.5.8 (cli) (built: Jul 6 2026 16:48:54) (NTS)
Copyright (c) The PHP Group
Built by https://github.com/docker-library/php
Zend Engine v4.5.8, Copyright (c) Zend Technologies
with Zend OPcache v8.5.8, Copyright (c), by Zend Technologies
Operating System
Debian 13.5
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu với ext/mysqli/mysqli_nonapi.c, đặc biệt là mysqli_common_connect và việc hạch toán kết nối persistent xung quanh các dòng được dẫn. Chạy reproducer được cung cấp với real_connect được bật, sau đó xác minh rằng việc tái sử dụng lặp lại giữ active_plinks ở 0 và cached_plinks ở 1 mà không thay đổi hành vi của non-real_connect.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- c, php
- Lĩnh vực
- databases
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Ít trao đổi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức phù hợp với người mới
- 68/100