From dev-return-63730-apmail-zookeeper-dev-archive=zookeeper.apache.org@zookeeper.apache.org Fri Sep 8 11:54:05 2017
Return-Path:
X-Original-To: apmail-zookeeper-dev-archive@www.apache.org
Delivered-To: apmail-zookeeper-dev-archive@www.apache.org
Received: from mail.apache.org (hermes.apache.org [140.211.11.3])
by minotaur.apache.org (Postfix) with SMTP id 497FD19014
for ; Fri, 8 Sep 2017 11:54:05 +0000 (UTC)
Received: (qmail 41140 invoked by uid 500); 8 Sep 2017 11:54:05 -0000
Delivered-To: apmail-zookeeper-dev-archive@zookeeper.apache.org
Received: (qmail 41077 invoked by uid 500); 8 Sep 2017 11:54:04 -0000
Mailing-List: contact dev-help@zookeeper.apache.org; run by ezmlm
Precedence: bulk
List-Help:
List-Unsubscribe:
List-Post:
List-Id:
Reply-To: dev@zookeeper.apache.org
Delivered-To: mailing list dev@zookeeper.apache.org
Received: (qmail 41066 invoked by uid 99); 8 Sep 2017 11:54:04 -0000
Received: from pnap-us-west-generic-nat.apache.org (HELO spamd2-us-west.apache.org) (209.188.14.142)
by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 08 Sep 2017 11:54:04 +0000
Received: from localhost (localhost [127.0.0.1])
by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id 926A31A776D
for ; Fri, 8 Sep 2017 11:54:03 +0000 (UTC)
X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org
X-Spam-Flag: NO
X-Spam-Score: -99.202
X-Spam-Level:
X-Spam-Status: No, score=-99.202 tagged_above=-999 required=6.31
tests=[KAM_ASCII_DIVIDERS=0.8, RP_MATCHES_RCVD=-0.001,
SPF_PASS=-0.001, USER_IN_WHITELIST=-100] autolearn=disabled
Received: from mx1-lw-eu.apache.org ([10.40.0.8])
by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024)
with ESMTP id iOpTmzjCPn7l for ;
Fri, 8 Sep 2017 11:54:01 +0000 (UTC)
Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139])
by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with ESMTP id 330D25FDBF
for ; Fri, 8 Sep 2017 11:54:01 +0000 (UTC)
Received: from jira-lw-us.apache.org (unknown [207.244.88.139])
by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id 59DBDE00C9
for ; Fri, 8 Sep 2017 11:54:00 +0000 (UTC)
Received: from jira-lw-us.apache.org (localhost [127.0.0.1])
by jira-lw-us.apache.org (ASF Mail Server at jira-lw-us.apache.org) with ESMTP id 0E06323F0D
for ; Fri, 8 Sep 2017 11:54:00 +0000 (UTC)
Date: Fri, 8 Sep 2017 11:54:00 +0000 (UTC)
From: "Alexander A. Strelets (JIRA)"
To: dev@zookeeper.apache.org
Message-ID:
In-Reply-To:
References:
Subject: [jira] [Updated] (ZOOKEEPER-2894) Memory and completions leak on
zookeeper_close.
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394
[ https://issues.apache.org/jira/browse/ZOOKEEPER-2894?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Alexander A. Strelets updated ZOOKEEPER-2894:
---------------------------------------------
Description:
ZooKeeper C Client *+single thread+* build
First of all, ZooKeeper C Client design allows calling _zookeeper_close()_ in two ways:
a) from a ZooKeeper callback handler (completion or watcher) which in turn is called through _zookeeper_process()_
b) and from other places -- i.e., when the call-stack does not pass through any of zookeeper mechanics prior to enter into mentioned _zookeeper_close()_
The issue described here below is +specific only to the case (b)+. So, it's Ok with the case (a).
When _zookeeper_close()_ is called in the (b) way, the following happens:
1. +If there are requests waiting for responses in _zh.sent_requests_ queue+, they all are removed from this queue and each of them is "completed" with personal fake response having status ZCLOSING. Such fake responses are put into _zh.completions_to_process_ queue. It's Ok
2. But then, _zh.completions_to_process_ queue is left unhandled. +Neither completion callbacks are called, nor dynamic memory allocated for fake responses is freed+
3. Different structures within _zh_ are dismissed and finally _zh_ is freed
This is illustrated on the screenshot attached to this ticket: you may see that the next instruction to execute will be _free(zh)_ while _zh.completions_to_process_ queue is not empty (see the "Variables" tab to the right).
*Consequently:*
1. At least there is definitely the +memory leak+ in the case (b) -- all the fake responses put into _zh.completions_to_process_ queue are lost after _free(zh)_
2. And it looks like a great misbehavior not to call completions on sent requests in the case (b) while they are called with ZCLOSING in the case (a) -- so, I think it's not "by design" but a +completions leak+
To reproduce the case (b) do the following:
- open ZooKeeper session, connect to a server, receive and process connected-watch, etc.
- then call for example _zoo_acreate()_ with valid arguments -- it shall return ZOK
- then, immediately after it returned, call _zookeeper_close()_
- note that completion callback handler for _zoo_acreate()_ will not be called
To reproduce the case (a) do about the same, but call _zookeeper_close()_ from a watcher or another completion callback handler.
To fix this I propose calling to _process_completions()_ from _destroy(zhandle_t *zh)_ as it is done in _handle_error(zhandle_t *zh,int rc)_.
was:
ZooKeeper C Client *+single thread+* build
First of all, ZooKeeper C Client design allows calling _zookeeper_close()_ in two ways:
a) from a ZooKeeper callback handler (completion or watcher) which in turn is called through _zookeeper_process()_
b) and from other places -- i.e., when the call-stack does not pass through any of zookeeper mechanics prior to enter into mentioned _zookeeper_close()_
The issue described here below is +specific only to the case (b)+. So, it's Ok with the case (a).
When _zookeeper_close()_ is called in the (b) way, the following happens:
1. If there are requests waiting for responses in _zh.sent_requests_ queue, they all are removed from this queue and each of them is "completed" with personal fake response having status ZCLOSING. Such fake responses are put into _zh.completions_to_process_ queue. It's Ok
2. But then, _zh.completions_to_process_ queue is left unhandled. +Neither completion callbacks are called, nor dynamic memory allocated for fake responses is freed.+
3. Different structures within _zh_ are dismissed and finally _zh_ is freed
This is illustrated on the screenshot attached to this ticket: you may see that the next instruction to execute will be _free(zh)_ while _zh.completions_to_process_ queue is not empty (see the "Variables" tab to the right).
*Consequently:*
1. At least there is definitely the +memory leak+ in the case (b) -- all the fake responses put into _zh.completions_to_process_ queue are lost after _free(zh)_
2. And it looks like a great misbehavior not to call completions on sent requests in the case (b) while they are called with ZCLOSING in the case (a) -- so, I think it's not "by design" but a +completions leak+
To reproduce the case (b) do the following:
- open ZooKeeper session, connect to a server, receive and process connected-watch, etc.
- then call for example _zoo_acreate()_ with valid arguments -- it shall return ZOK
- then, immediately after it returned, call _zookeeper_close()_
- note that completion callback handler for _zoo_acreate()_ will not be called
To reproduce the case (a) do about the same, but call _zookeeper_close()_ from a watcher or another completion callback handler.
To fix this I propose calling to _process_completions()_ from _destroy(zhandle_t *zh)_ as it is done in _handle_error(zhandle_t *zh,int rc)_.
> Memory and completions leak on zookeeper_close.
> -----------------------------------------------
>
> Key: ZOOKEEPER-2894
> URL: https://issues.apache.org/jira/browse/ZOOKEEPER-2894
> Project: ZooKeeper
> Issue Type: Bug
> Components: c client
> Affects Versions: 3.4.10
> Environment: Linux ubuntu 4.4.0-87-generic
> gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
> https://github.com/apache/zookeeper.git
> branch-3.4
> Reporter: Alexander A. Strelets
> Priority: Critical
> Fix For: 3.4.10
>
>
> ZooKeeper C Client *+single thread+* build
> First of all, ZooKeeper C Client design allows calling _zookeeper_close()_ in two ways:
> a) from a ZooKeeper callback handler (completion or watcher) which in turn is called through _zookeeper_process()_
> b) and from other places -- i.e., when the call-stack does not pass through any of zookeeper mechanics prior to enter into mentioned _zookeeper_close()_
> The issue described here below is +specific only to the case (b)+. So, it's Ok with the case (a).
> When _zookeeper_close()_ is called in the (b) way, the following happens:
> 1. +If there are requests waiting for responses in _zh.sent_requests_ queue+, they all are removed from this queue and each of them is "completed" with personal fake response having status ZCLOSING. Such fake responses are put into _zh.completions_to_process_ queue. It's Ok
> 2. But then, _zh.completions_to_process_ queue is left unhandled. +Neither completion callbacks are called, nor dynamic memory allocated for fake responses is freed+
> 3. Different structures within _zh_ are dismissed and finally _zh_ is freed
> This is illustrated on the screenshot attached to this ticket: you may see that the next instruction to execute will be _free(zh)_ while _zh.completions_to_process_ queue is not empty (see the "Variables" tab to the right).
> *Consequently:*
> 1. At least there is definitely the +memory leak+ in the case (b) -- all the fake responses put into _zh.completions_to_process_ queue are lost after _free(zh)_
> 2. And it looks like a great misbehavior not to call completions on sent requests in the case (b) while they are called with ZCLOSING in the case (a) -- so, I think it's not "by design" but a +completions leak+
> To reproduce the case (b) do the following:
> - open ZooKeeper session, connect to a server, receive and process connected-watch, etc.
> - then call for example _zoo_acreate()_ with valid arguments -- it shall return ZOK
> - then, immediately after it returned, call _zookeeper_close()_
> - note that completion callback handler for _zoo_acreate()_ will not be called
> To reproduce the case (a) do about the same, but call _zookeeper_close()_ from a watcher or another completion callback handler.
> To fix this I propose calling to _process_completions()_ from _destroy(zhandle_t *zh)_ as it is done in _handle_error(zhandle_t *zh,int rc)_.
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)