diff mbox series

[ovs-dev,v2,ovn] logical-fields: fix memory leak caused by initialize ovnfield_by_name twice

Message ID 1583389301-4259-1-git-send-email-damjan.skvarc@gmail.com
State Accepted
Headers show
Series [ovs-dev,v2,ovn] logical-fields: fix memory leak caused by initialize ovnfield_by_name twice | expand

Commit Message

Damijan Skvarc March 5, 2020, 6:21 a.m. UTC
ovnfield_by_name is hash of strings which is used to quickly find
field by name. This hash is initialized from ovn_init_symtab(). In case
the latter function is called multiple times then also ovnfield_by_name is
initialized multiple times but without freeing previously allocated
memory resources what cause memory leaks.  This actually happens in
ovn-controller which calls ovn_init_symtab() function twice, once from
ofctrl.c and the other time from lflow.c files.

Problem was solved by initializing ovnfield_by_name entity only once
and using design pattern from stopwatch.c or meta_flow.c files (ovs).

Problem was reported by valgrind with flood of messages (190) while executing
ovn test suite:

    ==5999== 47 (32 direct, 15 indirect) bytes in 1 blocks are definitely lost in loss record 86 of 102
    ==5999==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==5999==    by 0x50635D: xmalloc (util.c:138)
    ==5999==    by 0x4F6513: shash_add_nocopy__ (shash.c:109)
    ==5999==    by 0x4F6585: shash_add_nocopy (shash.c:121)
    ==5999==    by 0x4F65BD: shash_add (shash.c:129)
    ==5999==    by 0x4F6602: shash_add_once (shash.c:136)
    ==5999==    by 0x4395B7: ovn_init_symtab (logical-fields.c:261)
    ==5999==    by 0x406C91: main (ovn-controller.c:1750)

Signed-off-by: Damijan Skvarc <damjan.skvarc@gmail.com>
---
 controller/lflow.c           |  3 +--
 include/ovn/logical-fields.h |  1 -
 lib/logical-fields.c         | 39 +++++++++++++++++++++++++++------------
 3 files changed, 28 insertions(+), 15 deletions(-)

Comments

Ben Pfaff March 6, 2020, 11:12 p.m. UTC | #1
On Thu, Mar 05, 2020 at 07:21:41AM +0100, Damijan Skvarc wrote:
> ovnfield_by_name is hash of strings which is used to quickly find
> field by name. This hash is initialized from ovn_init_symtab(). In case
> the latter function is called multiple times then also ovnfield_by_name is
> initialized multiple times but without freeing previously allocated
> memory resources what cause memory leaks.  This actually happens in
> ovn-controller which calls ovn_init_symtab() function twice, once from
> ofctrl.c and the other time from lflow.c files.

Applied to master, thanks!
Numan Siddique March 10, 2020, 1:02 p.m. UTC | #2
On Sat, Mar 7, 2020 at 4:42 AM Ben Pfaff <blp@ovn.org> wrote:
>
> On Thu, Mar 05, 2020 at 07:21:41AM +0100, Damijan Skvarc wrote:
> > ovnfield_by_name is hash of strings which is used to quickly find
> > field by name. This hash is initialized from ovn_init_symtab(). In case
> > the latter function is called multiple times then also ovnfield_by_name is
> > initialized multiple times but without freeing previously allocated
> > memory resources what cause memory leaks.  This actually happens in
> > ovn-controller which calls ovn_init_symtab() function twice, once from
> > ofctrl.c and the other time from lflow.c files.
>
> Applied to master, thanks!

Hi Ben, Damijan,

I applied this patch to branch-20.03 as well for the following reasons
   - This patch fixes memory leak
   - branch-20.03 compilation is broken when configured with the flag
'--enable-sparse'
     Strangely, it used to compile for me last week. Even travis CI
passed for the latest commit in branch-20.03.
     I may have updated my sparse version. I'm using sparse 0.6.1 now.
    Applying this patch resolves the compilation issue.

    I'm seeing the below compilation error
   *****
   libtool: compile:  env REAL_CC=gcc "CHECK=sparse -Wsparse-error -I
/home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/include/sparse
-m64 -I /usr/local/include  " cgcc -target=x86_64 -DHAVE_CONFIG_H -I.
-I ./include -I ./include -I ./ovn -I ./include -I
/home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/include
-I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/include
-I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/lib
-I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/lib
-I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0
-I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0
-I ./lib -I ./lib -Wstrict-prototypes -Wall -Wextra -Wno-sign-compare
-Wpointer-arith -Wformat -Wformat-security -Wswitch-enum
-Wunused-parameter -Wbad-function-cast -Wcast-align
-Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes
-Wmissing-field-initializers -fno-strict-aliasing -Wswitch-bool
-Wlogical-not-parentheses -Wsizeof-array-argument -Wbool-compare
-Wshift-negative-value -Wduplicated-cond -Wshadow
-Wmultistatement-macros -Wcast-align=strict -Werror -Werror -g -O2 -MT
lib/logical-fields.lo -MD -MP -MF lib/.deps/logical-fields.Tpo -c
lib/logical-fields.c -o lib/logical-fields.o
lib/logical-fields.c:294:1: error: symbol 'ovn_destroy_ovnfields' was
not declared. Should it be static?
make[1]: *** [Makefile:2070: lib/logical-fields.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
   ***

Thanks
Numan


> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
Damijan Skvarc March 10, 2020, 1:40 p.m. UTC | #3
On Tue, Mar 10, 2020 at 2:02 PM Numan Siddique <numans@ovn.org> wrote:

> On Sat, Mar 7, 2020 at 4:42 AM Ben Pfaff <blp@ovn.org> wrote:
> >
> > On Thu, Mar 05, 2020 at 07:21:41AM +0100, Damijan Skvarc wrote:
> > > ovnfield_by_name is hash of strings which is used to quickly find
> > > field by name. This hash is initialized from ovn_init_symtab(). In case
> > > the latter function is called multiple times then also
> ovnfield_by_name is
> > > initialized multiple times but without freeing previously allocated
> > > memory resources what cause memory leaks.  This actually happens in
> > > ovn-controller which calls ovn_init_symtab() function twice, once from
> > > ofctrl.c and the other time from lflow.c files.
> >
> > Applied to master, thanks!
>
> Hi Ben, Damijan,
>
> I applied this patch to branch-20.03 as well for the following reasons
>    - This patch fixes memory leak
>    - branch-20.03 compilation is broken when configured with the flag
> '--enable-sparse'
>      Strangely, it used to compile for me last week. Even travis CI
> passed for the latest commit in branch-20.03.
>      I may have updated my sparse version. I'm using sparse 0.6.1 now.
>     Applying this patch resolves the compilation issue.
>
>     I'm seeing the below compilation error
>    *****
>    libtool: compile:  env REAL_CC=gcc "CHECK=sparse -Wsparse-error -I
>
> /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/include/sparse
> -m64 -I /usr/local/include  " cgcc -target=x86_64 -DHAVE_CONFIG_H -I.
> -I ./include -I ./include -I ./ovn -I ./include -I
> /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/include
> -I
> /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/include
> -I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/lib
> -I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/lib
> -I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0
> -I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0
> -I ./lib -I ./lib -Wstrict-prototypes -Wall -Wextra -Wno-sign-compare
> -Wpointer-arith -Wformat -Wformat-security -Wswitch-enum
> -Wunused-parameter -Wbad-function-cast -Wcast-align
> -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes
> -Wmissing-field-initializers -fno-strict-aliasing -Wswitch-bool
> -Wlogical-not-parentheses -Wsizeof-array-argument -Wbool-compare
> -Wshift-negative-value -Wduplicated-cond -Wshadow
> -Wmultistatement-macros -Wcast-align=strict -Werror -Werror -g -O2 -MT
> lib/logical-fields.lo -MD -MP -MF lib/.deps/logical-fields.Tpo -c
> lib/logical-fields.c -o lib/logical-fields.o
> lib/logical-fields.c:294:1: error: symbol 'ovn_destroy_ovnfields' was
> not declared. Should it be static?
>

hm, according to this message it is expected the ovn_destroy_ovnfields()
should be static, but in fact it is static. In the
past it used to be non-static function. Are you sure you are not dealing
with some older object file artifact?

make[1]: *** [Makefile:2070: lib/logical-fields.lo] Error 1
> make[1]: *** Waiting for unfinished jobs....
>    ***
>
> Thanks
> Numan
>
>
> > _______________________________________________
> > dev mailing list
> > dev@openvswitch.org
> > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >
>
Numan Siddique March 10, 2020, 3:51 p.m. UTC | #4
On Tue, Mar 10, 2020 at 7:10 PM Damijan Skvarc <damjan.skvarc@gmail.com> wrote:
>
> On Tue, Mar 10, 2020 at 2:02 PM Numan Siddique <numans@ovn.org> wrote:
>
> > On Sat, Mar 7, 2020 at 4:42 AM Ben Pfaff <blp@ovn.org> wrote:
> > >
> > > On Thu, Mar 05, 2020 at 07:21:41AM +0100, Damijan Skvarc wrote:
> > > > ovnfield_by_name is hash of strings which is used to quickly find
> > > > field by name. This hash is initialized from ovn_init_symtab(). In case
> > > > the latter function is called multiple times then also
> > ovnfield_by_name is
> > > > initialized multiple times but without freeing previously allocated
> > > > memory resources what cause memory leaks.  This actually happens in
> > > > ovn-controller which calls ovn_init_symtab() function twice, once from
> > > > ofctrl.c and the other time from lflow.c files.
> > >
> > > Applied to master, thanks!
> >
> > Hi Ben, Damijan,
> >
> > I applied this patch to branch-20.03 as well for the following reasons
> >    - This patch fixes memory leak
> >    - branch-20.03 compilation is broken when configured with the flag
> > '--enable-sparse'
> >      Strangely, it used to compile for me last week. Even travis CI
> > passed for the latest commit in branch-20.03.
> >      I may have updated my sparse version. I'm using sparse 0.6.1 now.
> >     Applying this patch resolves the compilation issue.
> >
> >     I'm seeing the below compilation error
> >    *****
> >    libtool: compile:  env REAL_CC=gcc "CHECK=sparse -Wsparse-error -I
> >
> > /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/include/sparse
> > -m64 -I /usr/local/include  " cgcc -target=x86_64 -DHAVE_CONFIG_H -I.
> > -I ./include -I ./include -I ./ovn -I ./include -I
> > /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/include
> > -I
> > /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/include
> > -I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/lib
> > -I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/lib
> > -I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0
> > -I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0
> > -I ./lib -I ./lib -Wstrict-prototypes -Wall -Wextra -Wno-sign-compare
> > -Wpointer-arith -Wformat -Wformat-security -Wswitch-enum
> > -Wunused-parameter -Wbad-function-cast -Wcast-align
> > -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes
> > -Wmissing-field-initializers -fno-strict-aliasing -Wswitch-bool
> > -Wlogical-not-parentheses -Wsizeof-array-argument -Wbool-compare
> > -Wshift-negative-value -Wduplicated-cond -Wshadow
> > -Wmultistatement-macros -Wcast-align=strict -Werror -Werror -g -O2 -MT
> > lib/logical-fields.lo -MD -MP -MF lib/.deps/logical-fields.Tpo -c
> > lib/logical-fields.c -o lib/logical-fields.o
> > lib/logical-fields.c:294:1: error: symbol 'ovn_destroy_ovnfields' was
> > not declared. Should it be static?
> >
>
> hm, according to this message it is expected the ovn_destroy_ovnfields()
> should be static, but in fact it is static. In the
> past it used to be non-static function. Are you sure you are not dealing
> with some older object file artifact?
>

Sorry for the confusion. I mean we see this compilation error without
your patch.
Without your patch, the function ovn_destroy_ovnfields() is in fact
non-static and
it is declared in include/ovn/logical-fields.h. But still sparse
complains about this.

Anyway, with your patch, the compilation is resolved because you've made
ovn_destroy_ovnfields() static.

And hence I backported your patch to branch-20.03.

Thanks
Numan

> make[1]: *** [Makefile:2070: lib/logical-fields.lo] Error 1
> > make[1]: *** Waiting for unfinished jobs....
> >    ***
> >
> > Thanks
> > Numan
> >
> >
> > > _______________________________________________
> > > dev mailing list
> > > dev@openvswitch.org
> > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> > >
> >
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
Damijan Skvarc March 10, 2020, 3:57 p.m. UTC | #5
thanks for sharing your information with me. Obviously I didn't understand
you well.
thanks, damijan

On Tue, 10 Mar 2020, 16:51 Numan Siddique, <numans@ovn.org> wrote:

> On Tue, Mar 10, 2020 at 7:10 PM Damijan Skvarc <damjan.skvarc@gmail.com>
> wrote:
> >
> > On Tue, Mar 10, 2020 at 2:02 PM Numan Siddique <numans@ovn.org> wrote:
> >
> > > On Sat, Mar 7, 2020 at 4:42 AM Ben Pfaff <blp@ovn.org> wrote:
> > > >
> > > > On Thu, Mar 05, 2020 at 07:21:41AM +0100, Damijan Skvarc wrote:
> > > > > ovnfield_by_name is hash of strings which is used to quickly find
> > > > > field by name. This hash is initialized from ovn_init_symtab(). In
> case
> > > > > the latter function is called multiple times then also
> > > ovnfield_by_name is
> > > > > initialized multiple times but without freeing previously allocated
> > > > > memory resources what cause memory leaks.  This actually happens in
> > > > > ovn-controller which calls ovn_init_symtab() function twice, once
> from
> > > > > ofctrl.c and the other time from lflow.c files.
> > > >
> > > > Applied to master, thanks!
> > >
> > > Hi Ben, Damijan,
> > >
> > > I applied this patch to branch-20.03 as well for the following reasons
> > >    - This patch fixes memory leak
> > >    - branch-20.03 compilation is broken when configured with the flag
> > > '--enable-sparse'
> > >      Strangely, it used to compile for me last week. Even travis CI
> > > passed for the latest commit in branch-20.03.
> > >      I may have updated my sparse version. I'm using sparse 0.6.1 now.
> > >     Applying this patch resolves the compilation issue.
> > >
> > >     I'm seeing the below compilation error
> > >    *****
> > >    libtool: compile:  env REAL_CC=gcc "CHECK=sparse -Wsparse-error -I
> > >
> > >
> /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/include/sparse
> > > -m64 -I /usr/local/include  " cgcc -target=x86_64 -DHAVE_CONFIG_H -I.
> > > -I ./include -I ./include -I ./ovn -I ./include -I
> > >
> /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/include
> > > -I
> > >
> /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/include
> > > -I
> /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/lib
> > > -I
> /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0/lib
> > > -I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0
> > > -I /home/nusiddiq/workspace_cpp/ovn_fdp/ovn2.13/ovn/openvswitch-2.13.0
> > > -I ./lib -I ./lib -Wstrict-prototypes -Wall -Wextra -Wno-sign-compare
> > > -Wpointer-arith -Wformat -Wformat-security -Wswitch-enum
> > > -Wunused-parameter -Wbad-function-cast -Wcast-align
> > > -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes
> > > -Wmissing-field-initializers -fno-strict-aliasing -Wswitch-bool
> > > -Wlogical-not-parentheses -Wsizeof-array-argument -Wbool-compare
> > > -Wshift-negative-value -Wduplicated-cond -Wshadow
> > > -Wmultistatement-macros -Wcast-align=strict -Werror -Werror -g -O2 -MT
> > > lib/logical-fields.lo -MD -MP -MF lib/.deps/logical-fields.Tpo -c
> > > lib/logical-fields.c -o lib/logical-fields.o
> > > lib/logical-fields.c:294:1: error: symbol 'ovn_destroy_ovnfields' was
> > > not declared. Should it be static?
> > >
> >
> > hm, according to this message it is expected the ovn_destroy_ovnfields()
> > should be static, but in fact it is static. In the
> > past it used to be non-static function. Are you sure you are not dealing
> > with some older object file artifact?
> >
>
> Sorry for the confusion. I mean we see this compilation error without
> your patch.
> Without your patch, the function ovn_destroy_ovnfields() is in fact
> non-static and
> it is declared in include/ovn/logical-fields.h. But still sparse
> complains about this.
>
> Anyway, with your patch, the compilation is resolved because you've made
> ovn_destroy_ovnfields() static.
>
> And hence I backported your patch to branch-20.03.
>
> Thanks
> Numan
>
> > make[1]: *** [Makefile:2070: lib/logical-fields.lo] Error 1
> > > make[1]: *** Waiting for unfinished jobs....
> > >    ***
> > >
> > > Thanks
> > > Numan
> > >
> > >
> > > > _______________________________________________
> > > > dev mailing list
> > > > dev@openvswitch.org
> > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> > > >
> > >
> > _______________________________________________
> > dev mailing list
> > dev@openvswitch.org
> > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >
>
diff mbox series

Patch

diff --git a/controller/lflow.c b/controller/lflow.c
index ee11fc6..143ea3c 100644
--- a/controller/lflow.c
+++ b/controller/lflow.c
@@ -827,7 +827,7 @@  lflow_handle_changed_neighbors(
     }
 }
 
-
+
 /* Translates logical flows in the Logical_Flow table in the OVN_SB database
  * into OpenFlow flows.  See ovn-architecture(7) for more information. */
 void
@@ -846,5 +846,4 @@  lflow_destroy(void)
 {
     expr_symtab_destroy(&symtab);
     shash_destroy(&symtab);
-    ovn_destroy_ovnfields();
 }
diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h
index 9b7c34f..c7bd2db 100644
--- a/include/ovn/logical-fields.h
+++ b/include/ovn/logical-fields.h
@@ -130,5 +130,4 @@  ovn_field_from_id(enum ovn_field_id id)
 const char *event_to_string(enum ovn_controller_event event);
 int string_to_event(const char *s);
 const struct ovn_field *ovn_field_from_name(const char *name);
-void ovn_destroy_ovnfields(void);
 #endif /* ovn/lib/logical-fields.h */
diff --git a/lib/logical-fields.c b/lib/logical-fields.c
index 25ace58..a007085 100644
--- a/lib/logical-fields.c
+++ b/lib/logical-fields.c
@@ -254,12 +254,6 @@  ovn_init_symtab(struct shash *symtab)
     expr_symtab_add_field(symtab, "sctp.src", MFF_SCTP_SRC, "sctp", false);
     expr_symtab_add_field(symtab, "sctp.dst", MFF_SCTP_DST, "sctp", false);
 
-    shash_init(&ovnfield_by_name);
-    for (int i = 0; i < OVN_FIELD_N_IDS; i++) {
-        const struct ovn_field *of = &ovn_fields[i];
-        ovs_assert(of->id == i); /* Fields must be in the enum order. */
-        shash_add_once(&ovnfield_by_name, of->name, of);
-    }
     expr_symtab_add_ovn_field(symtab, "icmp4.frag_mtu", OVN_ICMP4_FRAG_MTU);
 }
 
@@ -284,14 +278,35 @@  string_to_event(const char *s)
     return -1;
 }
 
-const struct ovn_field *
-ovn_field_from_name(const char *name)
+static void
+ovn_destroy_ovnfields(void)
 {
-    return shash_find_data(&ovnfield_by_name, name);
+    shash_destroy(&ovnfield_by_name);
 }
 
-void
-ovn_destroy_ovnfields(void)
+static void
+ovn_do_init_ovnfields(void)
 {
-    shash_destroy(&ovnfield_by_name);
+    shash_init(&ovnfield_by_name);
+    for (int i = 0; i < OVN_FIELD_N_IDS; i++) {
+       const struct ovn_field *of = &ovn_fields[i];
+       ovs_assert(of->id == i); /* Fields must be in the enum order. */
+       shash_add_once(&ovnfield_by_name, of->name, of);
+    }
+    atexit(ovn_destroy_ovnfields);
+}
+
+static void
+ovn_init_ovnfields(void)
+{
+    static pthread_once_t once = PTHREAD_ONCE_INIT;
+    pthread_once(&once, ovn_do_init_ovnfields);
+}
+
+const struct ovn_field *
+ovn_field_from_name(const char *name)
+{
+    ovn_init_ovnfields();
+
+    return shash_find_data(&ovnfield_by_name, name);
 }