php / php/php-src

ext/mysqli: mysqli double increments num_active_persistent when using real_connect

Abierto
#22,631 5 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Bug Extension: mysqli Status: Needs Triage
Lenguaje dominante
C
Estrellas
40.4k
Forks
8.1k
Merge medio
2 d 13 h
PR fusionados (30 d)
96

Descripción

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

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza con ext/mysqli/mysqli_nonapi.c, especialmente con mysqli_common_connect y el recuento de conexiones persistentes alrededor de las líneas citadas. Ejecuta el reproductor proporcionado con real_connect habilitado y, después, verifica que la reutilización repetida deje active_plinks en 0 y cached_plinks en 1 sin cambiar el comportamiento de non-real_connect.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
c, php
Área
databases
Tipo de issue
Error
Dificultad
3/5
Tiempo estimado
1-2 días
Estado de actividad
Tranquilo
Claridad
Bien especificado
Aptitud para principiantes
68/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.