Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:97901 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 56318 invoked from network); 20 Jan 2017 20:58:24 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 20 Jan 2017 20:58:24 -0000 Authentication-Results: pb1.pair.com smtp.mail=nikita.ppv@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=nikita.ppv@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.161.180 as permitted sender) X-PHP-List-Original-Sender: nikita.ppv@gmail.com X-Host-Fingerprint: 209.85.161.180 mail-yw0-f180.google.com Received: from [209.85.161.180] ([209.85.161.180:34911] helo=mail-yw0-f180.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id DE/B8-00729-EE972885 for ; Fri, 20 Jan 2017 15:58:22 -0500 Received: by mail-yw0-f180.google.com with SMTP id l19so103263707ywc.2 for ; Fri, 20 Jan 2017 12:58:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=e0tekhKCxFgMQ3o4jhLBrsQAOZsb37tO7EzG7KLhZkI=; b=T3ClMeOLJ6keBbgr+gvkxdXgrO7626/K0kN8wIwSJ3NlZt8MGl+evewS7VJ76Dtsqh lNVBqVpKx8zvfKK3VJOf1BulbrA8UX1xII8F7TR7K8g5HZihjzumgBN5LQrSVqVjLqIa Xx6SPGH6XgQge6CN/IoDZBhjCQv8Tx9yoVNczILQhIbXubeCyjUTIgGQC6ufqWV6O2am QBIrtwaxBS1n2FZEcj9PS8LXorZD280dg8u/cDaIn4439Lkr0qKuXMX/QTWVDa8x7jt8 cG4+zQ19czvNxFwFmDLiUBC2WZwHk7I28ZwH62wyTpE+hkxwXk+BNa3qn6fPwAP+bNG4 YVCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=e0tekhKCxFgMQ3o4jhLBrsQAOZsb37tO7EzG7KLhZkI=; b=q/G4BXVjxtY55AlJSSakocBNvCbr2YEYnsVrae/s8qLnyPWuA3T5V/NPru6RNed4O3 +rkzsv3Xz2wOp7wWcuIISOGZCkcrU2eWvdlk0/8yvLK53SAVeJx/YxWQzybizLc/MsOG B5GwbHC447IVDsicy8Lqnn0L0k1KlS5RtzSpeJYN0R3e5SU7vKzqDoqFmagjtxOAaF0K V6KjtaDSbwIGbjeU4Ywx5i6lFQjAcKvNarEIvFVP7RDfte/W1zGPbnCMj+cBEz0QoEvE wJXukgFB4GFqXGJYqkzBJOIR8IED9GGozt+EmnezsvUUwTSHXvjMDVOw56wU8LCOzQV/ qs8g== X-Gm-Message-State: AIkVDXLgHpCCpff2DBl1FbY47n7/+if90ei4mkOvCmK6K4Jvrcua8lcniMeCYmQHXEaFe0D2B1EUUOPFMDpgMQ== X-Received: by 10.129.141.6 with SMTP id d6mr12996869ywg.198.1484945899299; Fri, 20 Jan 2017 12:58:19 -0800 (PST) MIME-Version: 1.0 Received: by 10.129.80.215 with HTTP; Fri, 20 Jan 2017 12:58:18 -0800 (PST) In-Reply-To: References: Date: Fri, 20 Jan 2017 21:58:18 +0100 Message-ID: To: Rasmus Lerdorf Cc: PHP internals Content-Type: multipart/alternative; boundary=f403045e61fcd6aaaa05468ce8fb Subject: Re: [PHP-DEV] pdo_sqlite fd leak From: nikita.ppv@gmail.com (Nikita Popov) --f403045e61fcd6aaaa05468ce8fb Content-Type: text/plain; charset=UTF-8 On Fri, Jan 20, 2017 at 9:13 PM, Rasmus Lerdorf wrote: > 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 > From the docs for sqlite3_close(): > If the database connection is associated with unfinalized prepared statements or unfinished sqlite3_backup objects then sqlite3_close() will leave the database connection open and return SQLITE_BUSY . If sqlite3_close_v2() is called with unfinalized prepared statements and/or unfinished sqlite3_backups, then the database connection becomes an unusable "zombie" which will automatically be deallocated when the last prepared statement is finalized or the last sqlite3_backup is finished. The sqlite3_close_v2() interface is intended for use with host languages that are garbage collected, and where the order in which destructors are called is arbitrary. That sounds like it could be the source of the issue. Nikita --f403045e61fcd6aaaa05468ce8fb--