Uploaded image for project: 'Qpid Dispatch'
  1. Qpid Dispatch
  2. DISPATCH-848

Direct leak of 48 byte(s) in 1 object(s) allocated from qdr_core_subscribe in router_core/route_tables.c:149

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Minor
    • Resolution: Unresolved
    • 1.1.0
    • Backlog
    • Tests

    Description

      Compile Proton and Dispatch with the Address Sanitizer option (c.f. DISPATCH-809) and run ctest

      # proton
      cmake .. -DBUILD_GO=OFF -DENABLE_SANITIZERS=ON -DCMAKE_INSTALL_PREFIX=../install_asan -DCMAKE_BUILD_TYPE=Release -GNinja
      
      # dispatch
      cmake .. -DUSE_SANITIZERS=ON -DProton_DIR=`pwd`/../../qpid-proton/install_asan/lib64/cmake/Proton/ -DCMAKE_BUILD_TYPE=Release -GNinja
      
      LD_PRELOAD=/nix/store/zahs1kwq4742f6l6h7yy4mdj44zzc1kd-gcc-7-20170409-lib/lib/libasan.so ASAN_OPTIONS=symbolize=1,color=always LSAN_OPTIONS=suppressions=`pwd`/../../qpid-proton/LSan.supp PYTHONPATH=`pwd`/../../qpid-proton/install_asan/lib64/proton/bindings/python LD_LIBRARY_PATH=`pwd`/../../qpid-proton/install_asan/lib64 ctest -VV
      
      [...]
      9: Test Case parse_tree_tests.test_matches: PASS
      9: Test Case parse_tree_tests.test_multiple_matches: PASS
      9: 
      9: =================================================================
      9: ==25904==ERROR: LeakSanitizer: detected memory leaks
      9: 
      9: Direct leak of 48 byte(s) in 1 object(s) allocated from:
      9:     #0 0x7fb5442cb050 in __interceptor_malloc (/nix/store/zahs1kwq4742f6l6h7yy4mdj44zzc1kd-gcc-7-20170409-lib/lib/libasan.so+0xd9050)
      9:     #1 0x7fb543dd94fe in qdr_core_subscribe ../src/router_core/route_tables.c:149
      9:     #2 0x7fb543d89ff0 in IoAdapter_init ../src/python_embedded.c:548
      9:     #3 0x7fb542ba8ecd in type_call (/nix/store/1snk2wkpv97an87pk1842fgskl1vqhkr-python-2.7.14/lib/libpython2.7.so.1.0+0x9fecd)
      9: 
      9: -----------------------------------------------------
      9: Suppressions used:
      9:   count      bytes template
      9:    1310    2021760 dictresize
      9:     204     188272 _PyObject_GC_Malloc
      9:      45      39369 PyString_FromStringAndSize
      9:     308      15056 list_resize
      9:      11       9784 PyString_FromString
      9:       2       1280 _PyObject_GC_Resize
      9:    1035      24104 PyList_New
      9:      14        672 s_init
      9:       1         32 PyThread_allocate_lock
      9:      11      11097 type_new
      9:       3       3984 unicode_resize
      9:     179     204712 _PyUnicode_New.part.8
      9:      11       8028 PyObject_Realloc
      9:      37        120 _ctypes_alloc_format_string
      9:       3      24576 set_table_resize
      9: -----------------------------------------------------
      9: 
      9: SUMMARY: AddressSanitizer: 48 byte(s) leaked in 1 allocation(s).
       9/36 Test  #9: unit_tests ................................***Failed    0.21 sec
      

      The relevant functions are

      static int IoAdapter_init(IoAdapter *self, PyObject *args, PyObject *kwds)
      {
          PyObject *addr;
          char aclass    = 'L';
          char phase     = '0';
          int  treatment = QD_TREATMENT_ANYCAST_CLOSEST;
          if (!PyArg_ParseTuple(args, "OO|cci", &self->handler, &addr, &aclass, &phase, &treatment))
              return -1;
          if (!PyCallable_Check(self->handler)) {
              PyErr_SetString(PyExc_TypeError, "IoAdapter.__init__ handler is not callable");
              return -1;
          }
          if (treatment == QD_TREATMENT_ANYCAST_BALANCED) {
              PyErr_SetString(PyExc_TypeError, "IoAdapter: ANYCAST_BALANCED is not supported for in-process subscriptions");
              return -1;
          }
          Py_INCREF(self->handler);
          self->qd   = dispatch;
          self->core = qd_router_core(self->qd);
          const char *address = PyString_AsString(addr);
          if (!address) return -1;
          qd_error_clear();
          self->sub = qdr_core_subscribe(self->core, address, aclass, phase, treatment, qd_io_rx_handler, self);
          if (qd_error_code()) {
              PyErr_SetString(PyExc_RuntimeError, qd_error_message());
              return -1;
          }
          return 0;
      }
      
      static void IoAdapter_dealloc(IoAdapter* self)
      {
          qdr_core_unsubscribe(self->sub);
          Py_DECREF(self->handler);
          self->ob_type->tp_free((PyObject*)self);
      }
      
      static PyTypeObject IoAdapterType = {
          PyObject_HEAD_INIT(0)
          0,                         /* ob_size*/
          DISPATCH_MODULE ".IoAdapter",  /* tp_name*/
          sizeof(IoAdapter),         /* tp_basicsize*/
          0,                         /* tp_itemsize*/
          (destructor)IoAdapter_dealloc, /* tp_dealloc*/
          0,                         /* tp_print*/
          0,                         /* tp_getattr*/
          0,                         /* tp_setattr*/
          0,                         /* tp_compare*/
          0,                         /* tp_repr*/
          0,                         /* tp_as_number*/
          0,                         /* tp_as_sequence*/
          0,                         /* tp_as_mapping*/
          0,                         /* tp_hash */
          0,                         /* tp_call*/
          0,                         /* tp_str*/
          0,                         /* tp_getattro*/
          0,                         /* tp_setattro*/
          0,                         /* tp_as_buffer*/
          Py_TPFLAGS_DEFAULT,        /* tp_flags*/
          "Dispatch IO Adapter",     /* tp_doc */
          0,                         /* tp_traverse */
          0,                         /* tp_clear */
          0,                         /* tp_richcompare */
          0,                         /* tp_weaklistoffset */
          0,                         /* tp_iter */
          0,                         /* tp_iternext */
          IoAdapter_methods,         /* tp_methods */
          0,                         /* tp_members */
          0,                         /* tp_getset */
          0,                         /* tp_base */
          0,                         /* tp_dict */
          0,                         /* tp_descr_get */
          0,                         /* tp_descr_set */
          0,                         /* tp_dictoffset */
          (initproc)IoAdapter_init,  /* tp_init */
          0,                         /* tp_alloc */
          0,                         /* tp_new */
          0,                         /* tp_free */
          0,                         /* tp_is_gc */
          0,                         /* tp_bases */
          0,                         /* tp_mro */
          0,                         /* tp_cache */
          0,                         /* tp_subclasses */
          0,                         /* tp_weaklist */
          0,                         /* tp_del */
          0                          /* tp_version_tag */
      };
      

      I believe that there is indeed nothing that would free the sub field in IoAdapter.

      Depending on how this is triaged (real issue or not, I am myself a bit unsure about freeing memory in relation to Python) I may have more reports coming.

      Attachments

        1. LSan.supp
          0.4 kB
          Jiri Daněk

        Issue Links

          Activity

            People

              Unassigned Unassigned
              jdanek Jiri Daněk
              Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated: