Deepstream 6.1 python app doesn't exit after ctr+c causing device memory overload

Please provide complete information as applicable to your setup.

• Hardware Platform (Jetson / GPU) Jetson Xaxier
• DeepStream Version 6.1.0
• JetPack Version (valid for Jetson only)
• TensorRT Version 8.4
• NVIDIA GPU Driver Version (valid for GPU only)
• Issue Type( questions, new requirements, bugs) Memory overload
• How to reproduce the issue ? (This is for bugs. Including which sample app is using, the configuration files content, the command line used and other details for reproducing)
• Requirement details( This is for new requirement. Including the module name-for which plugin or for which sample application, the function description)

Hello,

I have been trying a modified version of deepstream-test4 app . But I have been facing a memory overload issue. When I run the App and press Ctr+c to close it , the App doesn’t finish itself. I had to do Ctr+Z to kill it but after doing so the memory allocated by deepstream wasn’t released. I end up having my device completely overloaded after just 2 or 3 runs. I have to restart it to release the memory.

The main modification was done on the osd_sink_pad_buffer_probe and main function as you can see below

def osd_sink_pad_buffer_probe(pad, info, u_data):
    frame_number = 0
    
    # Intiallizing object counter with 0.
    
    obj_counter = {
        PGIE_CLASS_ID_VEHICLE: 0,
        PGIE_CLASS_ID_PERSON: 0,
        PGIE_CLASS_ID_BICYCLE: 0,
        PGIE_CLASS_ID_ROADSIGN: 0
    }
   
    gst_buffer = info.get_buffer()
    if not gst_buffer:
        print("Unable to get GstBuffer ")
        return
    
    # Retrieve batch metadata from the gst_buffer
    # Note that pyds.gst_buffer_get_nvds_batch_meta() expects the
    # C address of gst_buffer as input, which is obtained with hash(gst_buffer)
  
    batch_meta = pyds.gst_buffer_get_nvds_batch_meta(hash(gst_buffer))
    if not batch_meta:
        return Gst.PadProbeReturn.OK
    l_frame = batch_meta.frame_meta_list
    while l_frame is not None:
        try:

            # Note that l_frame.data needs a cast to pyds.NvDsFrameMeta
            # The casting is done by pyds.NvDsFrameMeta.cast()
            # The casting also keeps ownership of the underlying memory
            # in the C code, so the Python garbage collector will leave
            # it alone.
                    
            frame_meta = pyds.NvDsFrameMeta.cast(l_frame.data)
        except StopIteration:
            continue
        is_first_object = True
        n_frame = pyds.get_nvds_buf_surface(hash(gst_buffer), frame_meta.batch_id)

        # Short example of attribute access for frame_meta:
        # print("Frame Number is ", frame_meta.frame_num)
        # print("Source id is ", frame_meta.source_id)
        # print("Batch id is ", frame_meta.batch_id)
        # print("Source Frame Width ", frame_meta.source_frame_width)
        # print("Source Frame Height ", frame_meta.source_frame_height)
        # print("Num object meta ", frame_meta.num_obj_meta)

        frame_number = frame_meta.frame_num
        l_obj = frame_meta.obj_meta_list
        t_obj = frame_meta.obj_meta_list
        person_meta_list =[]

        
        while t_obj is not None:
            try:
                obj_meta = pyds.NvDsObjectMeta.cast(t_obj.data)
            except StopIteration:
                continue
            obj_meta.rect_params.border_color.set(0,0,1,1)
            if (obj_meta.class_id==0) and(obj_meta.confidence>0.5):
                person_meta_list.append(obj_meta)
            # elif (obj_meta.confidence<0.5):
            #      obj_meta.rect_params.border_width=0
            try:
                t_obj = t_obj.next
            except StopIteration:
                break

        for i in range(len(person_meta_list)):
            person =person_meta_list[i]
            l_obj = frame_meta.obj_meta_list
            is_wearing_vest =False
            is_wearing_helmet =False
            violation_type =0

            while l_obj is not None:
                try:
                    obj_meta = pyds.NvDsObjectMeta.cast(l_obj.data)
                except StopIteration:
                    continue
                if obj_meta.class_id==1 and bb_intersection_over_union(person,obj_meta)>0.8:
                    is_wearing_vest =True
                    

                if obj_meta.class_id==2 and bb_intersection_over_union(person,obj_meta)>0.8:
                    is_wearing_helmet =True
                    violation_type =2
                try:
                    l_obj = l_obj.next
                except StopIteration:
                    break

            # Update the object text display
            txt_params = person.text_params
            obj_counter[person.class_id] += 1
            txt_params.font_params.font_name = "Serif"
            txt_params.font_params.font_size = 10
            txt_params.font_params.font_color.set(1.0, 1.0, 1.0, 1.0)
            txt_params.set_bg_clr = 1

            # set(red, green, blue, alpha); set to Black
            txt_params.text_bg_clr.set(0.0, 0.0, 0.0, 1.0)

            if (person.object_id in  track_id_dict) and  (track_id_dict[person.object_id]>MAX_ALLOW_VIOLATION):
                if (not is_wearing_vest):
                    violation_type =1
                if (not is_wearing_helmet):
                    violation_type =2
                if (not is_wearing_vest) and (not is_wearing_helmet):
                    violation_type =3
            elif (not is_wearing_vest) or (not is_wearing_helmet):
                track_id_dict[person.object_id]=+1

            if (violation_type!=0):

                # Set display_text. Any existing display_text string will be
                # freed by the bindings module.
                ##n_frame = draw_bounding_boxes(n_frame, person, person.confidence)

                txt_params.display_text = violation_classes_str[violation_type]
                msg_meta = pyds.alloc_nvds_event_msg_meta()
                person.rect_params.border_color.set(1,0,0,1)
                msg_meta.bbox.top = person.rect_params.top
                msg_meta.bbox.left = person.rect_params.left
                msg_meta.bbox.width = person.rect_params.width
                msg_meta.bbox.height = person.rect_params.height
                msg_meta.frameId = frame_number
                msg_meta.trackingId = long_to_uint64(person.object_id)
                msg_meta.confidence = person.confidence
                msg_meta = generate_violation_msg_meta(msg_meta, person.class_id, violation_type)
                user_event_meta = pyds.nvds_acquire_user_meta_from_pool(
                    batch_meta)
                if user_event_meta:
                    user_event_meta.user_meta_data = msg_meta
                    user_event_meta.base_meta.meta_type = pyds.NvDsMetaType.NVDS_EVENT_MSG_META
                    # Setting callbacks in the event msg meta. The bindings
                    # layer will wrap these callables in C functions.
                    # Currently only one set of callbacks is supported.
                    pyds.user_copyfunc(user_event_meta, meta_copy_func)
                    pyds.user_releasefunc(user_event_meta, meta_free_func)
                    pyds.nvds_add_user_meta_to_frame(frame_meta,
                                                     user_event_meta)
                else:
                    print("Error in attaching event meta to buffer\n")
            else:
                txt_params.display_text = violation_classes_str[0]
        
       
        # # convert python array into numpy array format in the copy mode.
        # frame_copy = np.array(n_frame, copy=True, order='C')
        # # convert the array into cv2 default color format
        # frame_copy = cv2.cvtColor(frame_copy, cv2.COLOR_RGBA2BGRA)
        # img_path = "{}stream_{}/frame_{}.jpg".format(folder_name, frame_meta.pad_index, frame_number)
        # print(img_path)
        # cv2.imwrite(img_path, frame_copy)
        try:
            l_frame = l_frame.next
        except StopIteration:
            break


    print("Frame Number =", frame_number,"Person Count =",obj_counter[PGIE_CLASS_ID_PERSON])
    return Gst.PadProbeReturn.OK

can you narrow down this issue by simplifying the code? which line code will cause this issue?

Hello Fanzh,

I found the issue comes from the osd_sink_pad_buffer_probe function. And I think it starts from line 115 after entering the part that sends user_event_meta to the broker. Because I have realized I keep receiving the meta-data from my subscribers after doing clt+c.

Hi Fanzh ,
When trying to crt+c I have this error message . I think they are related.
(python3:14597): GStreamer-CRITICAL **: 15:30:20.909:
Trying to dispose element file-source, but it is in PLAYING instead of the NULL state.
You need to explicitly set elements to the NULL state before
dropping the final reference, to allow them to clean up.
This problem may also be caused by a refcounting bug in the
application or some element.

I can’t reproduce this issue with the official sample on jetson orin + ds6.2. here is the command:
python3 deepstream_test_4.py -i /opt/nvidia/deepstream/deepstream/samples/streams/sample_720p.h264 -p /opt/nvidia/deepstream/deepstream/lib/libnvds_kafka_proto.so --conn-str=“localhost;9092” -t deepstream -s 0 --no-display
here is the result:


need to check your code.

after replace osd_sink_pad_buffer_probe in the official sample, I still can’t reproduce this issue with the command above.

Hi fanzh , you right.
There was an issue in my code, a sort of infinite loop. After fixing it can exit naturally.

Thank you.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.