I have been chasing a really odd fd leak which I haven't been able to
reproduce manually. The code involved is about as simple as you can get:

class C {
    public static function fn($arg) {
        $pdo = new PDO('sqlite:/var/dbs/file.db');
        $query = $pdo->prepare("SELECT * FROM tb WHERE id = ?");
        $query->execute([$arg]);
        $result = $query->fetch(PDO::FETCH_ASSOC);

        if (!$result) {
            throw new RuntimeException("not found" );
        }

        return [
            "a" => $result['a'],
            "b" => $result['b']
        ];
    }
}

The symptoms are:

   - It always starts with a max_execution timeout in the *$pdo->prepare()*
   call
   - Many hours after this timeout the httpd process runs out of FDs and
   lsof shows the httpd process with ~1000 fds open on */var/dbs/file.db*

The file.db itself is only read from PHP and isn't being updated in the
background by anything. mtime is months ago, but this happens sporadically
on a single server out of dozens about once every couple of days. These
servers are getting hit hard so it takes hundreds of millions of requests
to trigger whatever condition is causing this.

It feels like it should be something related to timeouts and the
*sqlite_handle_closer()
*call:

https://github.com/php/php-src/blob/PHP-7.0/ext/pdo_sqlite/sqlite_driver.c#L155-L175

but I have been staring at this code and comparing it to the other pdo
drivers and I don't see what makes *pdo_sqlite* special here.
This is on PHP 7.0.10 but this code hasn't changed significantly in 7.1 and
master. Anyone see anything in PDO that could possibly prevent the
*sqlite3_close()* call from being executed, especially in edge conditions
around an execution timeout?

-Rasmus

Reply via email to