def track(self, thread_id, frame, frame_id_to_lineno, frame_custom_thread_id=None):
        '''
        :param thread_id:
            The thread id to be used for this frame.

        :param frame:
            The topmost frame which is suspended at the given thread.

        :param frame_id_to_lineno:
            If available, the line number for the frame will be gotten from this dict,
            otherwise frame.f_lineno will be used (needed for unhandled exceptions as
            the place where we report may be different from the place where it's raised).

        :param frame_custom_thread_id:
            If None this this is the id of the thread id for the custom frame (i.e.: coroutine).
        '''
        with self._lock:
            coroutine_or_main_thread_id = frame_custom_thread_id or thread_id

            if coroutine_or_main_thread_id in self._suspended_frames_manager._thread_id_to_tracker:
                sys.stderr.write('pydevd: Something is wrong. Tracker being added twice to the same thread id.\n')

            self._suspended_frames_manager._thread_id_to_tracker[coroutine_or_main_thread_id] = self
            self._main_thread_id = thread_id
            self._frame_id_to_lineno = frame_id_to_lineno

            frame_ids_from_thread = self._thread_id_to_frame_ids.setdefault(
                coroutine_or_main_thread_id, [])

            while frame is not None:
                frame_id = id(frame)
                self._frame_id_to_frame[frame_id] = frame
                _FrameVariable(frame, self._register_variable)  # Instancing is enough to register.
                self._suspended_frames_manager._variable_reference_to_frames_tracker[frame_id] = self
                frame_ids_from_thread.append(frame_id)

                self._frame_id_to_main_thread_id[frame_id] = thread_id

                frame = frame.f_back
:param thread_id:
            The thread id to be used for this frame.

        :param frame:
            The topmost frame which is suspended at the given thread.

        :param frame_id_to_lineno:
            If available, the line number for the frame will be gotten from this dict,
            otherwise frame.f_lineno will be used (needed for unhandled exceptions as
            the place where we report may be different from the place where it's raised).

        :param frame_custom_thread_id:
            If None this this is the id of the thread id for the custom frame (i.e.: coroutine).