docs: def _line_tracer(self, frame, exc_info=False):
          """This function is called when debugger has decided that it must
          stop or break at this frame."""
          # next logging statement commented for performance
          _logger.f_debug("user_line() with " 
                          "threadName=%s, frame=%s, frame.f_code=%s, self.mainpyfile=%s,"
                          "self.should_break_here()=%s, self.should_stop_here()=%s\n",
                           threading.currentThread().name,
                           hex(id(frame)),
                           frame.f_code,
                           self.mainpyfile,
                           self.should_break_here(frame),
                           self.should_stop_here(frame))
  
          # next lines allow to focus debugging on only one thread
          if self.debugged_thread_ident is None:
              self.debugged_thread_ident = threading.currentThread().ident
              self.debugged_thread_name = threading.currentThread().name
          else:
              if threading.currentThread().ident != self.debugged_thread_ident:
                  return
  
          # Acquire Breakpoint Lock before sending break command to remote client
          self._active_breakpoint_lock.acquire()
          self.status = 'stopped'
          frames = self.dump_frames(frame)
          exception=None
          warning_messages = []
          if exc_info:
              exception = {
                  'type': IKPdbRepr(exc_info[1]),
                  'info': exc_info[1].args[0]
              }
  
          if self.stop_at_first_statement:
              warning_messages = ["IKP3db stopped so that you can setup some "
                                  "breakpoints before 'Resuming' execution."]
              self.stop_at_first_statement = False
  
          remote_client.send('programBreak', 
                             frames=frames,
                             threads= self.get_threads(),
                             result={'executionStatus': 'stopped'},  #=self.status
                             warning_messages=warning_messages,
                             exception=exception)
                             
          # Enter a loop to process commands sent by client
          while True:
              command = self._command_q.get()
  
              if command['cmd'] == 'resume':
                  self.setup_resume()
                  break
              
              elif command['cmd'] == 'stepOver':
                  self.setup_step_over(frame)
                  break
              
              elif command['cmd'] == 'stepInto':
                  self.setup_step_into(frame)
                  break
              
              elif command['cmd'] == 'stepOut':
                  self.setup_step_out(frame)
                  break
              
              elif command['cmd'] == 'evaluate':
                  value, result_type = self.evaluate(command['frame'], 
                                                     command['expression'], 
                                                     command['global'], 
                                                     disable_break=command['disableBreak'])
                  remote_client.reply(command['obj'], {'value': value, 'type': result_type})
  
              elif command['cmd'] == 'getProperties':
                  error_messages = []
                  if command.get('id', False):
                      po_value = ctypes.cast(command['id'], ctypes.py_object).value
                      result={'properties': self.extract_object_properties(po_value) or []}
                      command_exec_status = 'ok'
                  else:
                      result={'properties': self.extract_object_properties(None) or []}
                      command_exec_status = 'ok'
                      
                  _logger.e_debug("    => %s", result)
                  remote_client.reply(command['obj'], result, 
                                      command_exec_status=command_exec_status,
                                      error_messages=error_messages)
  
              elif command['cmd'] == 'setVariable':
                  error_messages = []
                  result = {}
                  command_exec_status = 'ok'
                  # TODO: Rework to use id now that we are in right thread context
                  err_message = self.let_variable(command['frame'], 
                                                  command['name'], 
                                                  command['value'])
                  if err_message:
                      command_exec_status = 'error'
                      msg = "setVariable(%s=%s) failed with error: %s" % (command['name'], 
                                                                          command['value'],
                                                                          err_message)
                      error_messages = [msg]
                      _logger.e_error(msg)
                  remote_client.reply(command['obj'], 
                                      result,
                                      command_exec_status=command_exec_status,
                                      error_messages=error_messages)
                                      
              elif command['cmd'] == '_InternalQuit':
                  _logger.x_critical("Exiting tracer upon reception of _Internal"
                                     "Quit  command")
                  raise IKPdbQuit()                                    
  
              else:
                  _logger.x_critical("Unknown command: %s received by _line_tracer()" % resume_command)
                  raise IKPdbQuit()
  
          self.status = 'running'
          self._active_breakpoint_lock.release()
          return