@Override
    protected void execute(final DataRequestMonitor<FormattedValueDMData> rm) {
      DsfSession session = DsfSession.getSession(frame.getSessionId());
      IExpressions expressions = dsfServicesTracker.getService(IExpressions.class);
      if (expressions == null) {
        rm.setStatus(
            DsfUIPlugin.newErrorStatus(
                IDsfStatusConstants.REQUEST_FAILED, "No expression service", null)); // $NON-NLS-1$
        rm.done();
        return;
      }
      IExpressionDMContext expressionDMC = expressions.createExpression(frame, expression);
      FormattedValueDMContext formattedValueContext =
          expressions.getFormattedValueContext(expressionDMC, getHoverFormat());
      expressions.getFormattedExpressionValue(
          formattedValueContext,
          new DataRequestMonitor<FormattedValueDMData>(session.getExecutor(), rm) {
            @Override
            protected void handleSuccess() {
              rm.setData(getData());
              rm.done();
            }

            @Override
            protected void handleFailure() {
              rm.done();
            }
          });
    }
示例#2
0
    @Override
    public IStatus runInUIThread(IProgressMonitor monitor) {
      final Status NO_PID_STATUS =
          new Status(
              IStatus.ERROR,
              GdbUIPlugin.PLUGIN_ID,
              -1,
              LaunchMessages.getString(
                  "LocalAttachLaunchDelegate.No_Process_ID_selected"), //$NON-NLS-1$
              null);

      try {
        PrompterInfo info = new PrompterInfo(fNewProcessSupported, fProcessList);
        Object result = new ProcessPrompter().handleStatus(null, info);
        if (result == null) {
          fRequestMonitor.cancel();
        } else if (result instanceof IProcessExtendedInfo[] || result instanceof String) {
          fRequestMonitor.setData(result);
        } else {
          fRequestMonitor.setStatus(NO_PID_STATUS);
        }
      } catch (CoreException e) {
        fRequestMonitor.setStatus(NO_PID_STATUS);
      }
      fRequestMonitor.done();

      return Status.OK_STATUS;
    }
示例#3
0
  @Override
  public void getCPUs(
      final IHardwareTargetDMContext dmc, final DataRequestMonitor<ICPUDMContext[]> rm) {
    if (!fSessionInitializationComplete) {
      // We are not ready to answer yet
      rm.done(
          new Status(
              IStatus.ERROR,
              GdbPlugin.PLUGIN_ID,
              INVALID_STATE,
              "Debug session not initialized yet",
              null)); //$NON-NLS-1$
      return;
    }

    if (supportsProcPseudoFS()) {
      fFetchCPUInfoCache.execute(
          new MIMetaGetCPUInfo(fCommandControl.getContext()),
          new ImmediateDataRequestMonitor<MIMetaGetCPUInfoInfo>() {
            @Override
            protected void handleSuccess() {
              rm.done(parseCoresInfoForCPUs(dmc, getData().getInfo()));
            }
          });
    } else {
      // No way to know the CPUs for Windows session.
      rm.done(
          new Status(
              IStatus.ERROR,
              GdbPlugin.PLUGIN_ID,
              NOT_SUPPORTED,
              "Operation not supported",
              null)); //$NON-NLS-1$
    }
  }
示例#4
0
  /* (non-Javadoc)
   * @see org.eclipse.cdt.dsf.debug.service.IDisassembly#getMixedInstructions(org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext, java.lang.String, int, int, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
   */
  public void getMixedInstructions(
      IDisassemblyDMContext context,
      String filename,
      int linenum,
      int lines,
      final DataRequestMonitor<IMixedInstruction[]> drm) {
    // Validate the context
    if (context == null) {
      drm.setStatus(
          new Status(
              IStatus.ERROR,
              GdbPlugin.PLUGIN_ID,
              INTERNAL_ERROR,
              "Unknown context type",
              null)); //$NON-NLS-1$);
      drm.done();
      return;
    }

    // Go for it
    fConnection.queueCommand(
        fCommandFactory.createMIDataDisassemble(context, filename, linenum, lines, true),
        new DataRequestMonitor<MIDataDisassembleInfo>(getExecutor(), drm) {
          @Override
          protected void handleSuccess() {
            IMixedInstruction[] result = getData().getMIMixedCode();
            drm.setData(result);
            drm.done();
          }
        });
  }
示例#5
0
  /* (non-Javadoc)
   * @see org.eclipse.cdt.dsf.debug.service.IDisassembly#getInstructions(org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext, java.math.BigInteger, java.math.BigInteger, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
   */
  public void getInstructions(
      IDisassemblyDMContext context,
      BigInteger startAddress,
      BigInteger endAddress,
      final DataRequestMonitor<IInstruction[]> drm) {
    // Validate the context
    if (context == null) {
      drm.setStatus(
          new Status(
              IStatus.ERROR,
              GdbPlugin.PLUGIN_ID,
              INTERNAL_ERROR,
              "Unknown context type",
              null)); //$NON-NLS-1$);
      drm.done();
      return;
    }

    // Go for it
    String start = (startAddress != null) ? startAddress.toString() : "$pc"; // $NON-NLS-1$
    String end = (endAddress != null) ? endAddress.toString() : "$pc + 100"; // $NON-NLS-1$
    fConnection.queueCommand(
        fCommandFactory.createMIDataDisassemble(context, start, end, false),
        new DataRequestMonitor<MIDataDisassembleInfo>(getExecutor(), drm) {
          @Override
          protected void handleSuccess() {
            IInstruction[] result = getData().getMIAssemblyCode();
            drm.setData(result);
            drm.done();
          }
        });
  }
示例#6
0
  @Override
  public void getExecutionData(IDMContext dmc, DataRequestMonitor<IDMData> rm) {
    if (dmc instanceof ICoreDMContext) {
      rm.done(
          new Status(
              IStatus.ERROR,
              GdbPlugin.PLUGIN_ID,
              INVALID_HANDLE,
              "Not done yet",
              null)); //$NON-NLS-1$
    } else if (dmc instanceof ICPUDMContext) {
      rm.done(
          new Status(
              IStatus.ERROR,
              GdbPlugin.PLUGIN_ID,
              INVALID_HANDLE,
              "Not done yet",
              null)); //$NON-NLS-1$

    } else {
      rm.done(
          new Status(
              IStatus.ERROR,
              GdbPlugin.PLUGIN_ID,
              INVALID_HANDLE,
              "Invalid DMC type",
              null)); //$NON-NLS-1$
    }
  }
  private void processCountRequest(CountRequest request) {
    @SuppressWarnings("unchecked") // Suppress warning about lost type info.
    DataRequestMonitor<Integer> rm = (DataRequestMonitor<Integer>) request.fRequestMonitor;

    rm.setData(fCount);
    rm.done();
  }
示例#8
0
  /**
   * For a given "load info" request, this method processes the load obtained from the proc stat
   * parser and creates/sends the response.
   *
   * @param context
   * @param rm
   * @param loads
   */
  private void processLoads(
      final IDMContext context,
      final DataRequestMonitor<ILoadInfo> rm,
      final ProcStatCoreLoads loads) {

    // problem with fetching load info
    if (loads == null) {
      rm.done(
          new Status(
              IStatus.ERROR,
              GdbPlugin.PLUGIN_ID,
              INTERNAL_ERROR,
              "Can't get load info",
              null)); //$NON-NLS-1$
      return;
    }
    // core context?
    if (context instanceof ICoreDMContext) {
      String coreId = ((ICoreDMContext) context).getId();
      // Integer precision sufficient for our purpose
      float load = loads.getLoad(coreId);
      rm.done(new GDBLoadInfo(Integer.toString((int) load)));
    } else if (context instanceof ICPUDMContext) {
      // get the list of cores in that CPU
      getCores(
          context,
          new ImmediateDataRequestMonitor<ICoreDMContext[]>() {
            @Override
            protected void handleCompleted() {
              ICoreDMContext[] coreContexts = getData();

              if (!isSuccess() || coreContexts == null || coreContexts.length < 1) {
                // Unable to get any core data
                rm.done(
                    new Status(
                        IStatus.ERROR,
                        GdbPlugin.PLUGIN_ID,
                        INTERNAL_ERROR,
                        "Can't get load info for CPU",
                        null)); //$NON-NLS-1$
                return;
              }

              int i = 0;
              float load = 0.0f;
              // compute the average load of cores in that CPU
              for (ICoreDMContext coreCtx : coreContexts) {
                String coreId = coreCtx.getId();
                load += loads.getLoad(coreId);
                i++;
              }
              load /= i;
              rm.done(new GDBLoadInfo(Integer.toString((int) load)));
            }
          });
    }
  }
 @Override
 public void getValue(int index, DataRequestMonitor<Integer> rm) {
   if (!fShutdown.get()) {
     fQueue.add(new ItemRequest(index, rm));
   } else {
     rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Supplier shut down"));
     rm.done();
   }
 }
  private void processItemRequest(ItemRequest request) {
    @SuppressWarnings("unchecked") // Suppress warning about lost type info.
    DataRequestMonitor<Integer> rm = (DataRequestMonitor<Integer>) request.fRequestMonitor;

    if (fChangedValues.containsKey(request.fIndex)) {
      rm.setData(fChangedValues.get(request.fIndex));
    } else {
      rm.setData(request.fIndex);
    }
    rm.done();
  }
  /** Start executing the program. */
  @Execute
  public void stepStartExecution(final RequestMonitor rm) {
    if (fBackend.getSessionType() != SessionType.CORE) {
      // Overwrite the program name to use the binary name that was specified.
      // This is important for multi-process
      // Bug 342351
      fAttributes.put(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, fBinaryName);

      fProcService.start(
          getContainerContext(),
          fAttributes,
          new DataRequestMonitor<IContainerDMContext>(ImmediateExecutor.getInstance(), rm) {
            @Override
            protected void handleSuccess() {
              assert getData() instanceof IMIContainerDMContext;

              // Set the container that we created
              setContainerContext(
                  DMContexts.getAncestorOfType(getData(), IMIContainerDMContext.class));
              fDataRequestMonitor.setData(getContainerContext());

              // Don't call fDataRequestMonitor.done(), the sequence will
              // automatically do that when it completes;
              rm.done();
            }
          });
    } else {
      fDataRequestMonitor.setData(getContainerContext());
      rm.done();
    }
  }
示例#12
0
 /** @since 4.2 */
 @Override
 public void getResourceClasses(IDMContext dmc, DataRequestMonitor<IResourceClass[]> rm) {
   rm.done(
       new Status(
           IStatus.ERROR,
           GdbPlugin.PLUGIN_ID,
           NOT_SUPPORTED,
           "Operation not supported",
           null)); //$NON-NLS-1$
 }
示例#13
0
  @Override
  public void sourceContainersChanged(
      final ISourceLookupDMContext sourceLookupCtx, final DataRequestMonitor<Boolean> rm) {
    if (!fDirectors.containsKey(sourceLookupCtx)) {
      rm.setStatus(
          new Status(
              IStatus.ERROR,
              GdbPlugin.PLUGIN_ID,
              IDsfStatusConstants.INVALID_HANDLE,
              "No source director configured for given context",
              null)); //$NON-NLS-1$ );
      rm.done();
      return;
    }

    Map<String, String> entries = getSubstitutionsPaths(sourceLookupCtx);
    if (entries.equals(fCachedEntries)) {
      rm.done(false);
    } else {
      /*
       * Issue the clear and set commands back to back so that the
       * executor thread atomically changes the source lookup settings.
       * Any commands to GDB issued after this call will get the new
       * source substitute settings.
       */
      CountingRequestMonitor countingRm =
          new CountingRequestMonitor(getExecutor(), rm) {
            @Override
            protected void handleSuccess() {
              rm.done(true);
            }
          };
      fCommand.queueCommand(
          fCommandFactory.createCLIUnsetSubstitutePath(sourceLookupCtx),
          new DataRequestMonitor<MIInfo>(getExecutor(), countingRm));
      initializeSourceSubstitutions(sourceLookupCtx, new RequestMonitor(getExecutor(), countingRm));
      countingRm.setDoneCount(2);
    }
  }
示例#14
0
    @Override
    protected void execute(final DataRequestMonitor<V> rm) {
      /*
       * We're in another dispatch, so we must guard against executor
       * shutdown again.
       */
      final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
      if (session == null) {
        rm.setStatus(
            new Status(
                IStatus.ERROR,
                DsfUIPlugin.PLUGIN_ID,
                IDsfStatusConstants.INVALID_STATE,
                "Debug session already shut down.",
                null)); //$NON-NLS-1$
        rm.done();
        return;
      }

      /*
       * Guard against a disposed service
       */
      IRegisters service = getService();
      if (service == null) {
        rm.setStatus(
            new Status(
                IStatus.ERROR,
                DsfUIPlugin.PLUGIN_ID,
                IDsfStatusConstants.INVALID_STATE,
                "Service unavailable",
                null)); //$NON-NLS-1$
        rm.done();
        return;
      }

      doExecute(service, rm);
    }
    @Override
    protected IStatus run(IProgressMonitor monitor) {
      final IStatus promptStatus =
          new Status(
              IStatus.INFO,
              "org.eclipse.debug.ui",
              200 /*STATUS_HANDLER_PROMPT*/,
              "",
              null); //$NON-NLS-1$//$NON-NLS-2$
      final IStatus filePrompt =
          new Status(
              IStatus.INFO,
              "org.eclipse.cdt.dsf.gdb.ui",
              1001,
              "",
              null); //$NON-NLS-1$//$NON-NLS-2$
      // consult a status handler
      final IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(promptStatus);

      final Status NO_CORE_STATUS =
          new Status(
              IStatus.ERROR,
              GdbPlugin.PLUGIN_ID,
              -1,
              LaunchMessages.getString("LocalCDILaunchDelegate.6"), // $NON-NLS-1$
              null);

      if (prompter == null) {
        fRequestMonitor.setStatus(NO_CORE_STATUS);
        fRequestMonitor.done();
        return Status.OK_STATUS;
      }

      try {
        Object result = prompter.handleStatus(filePrompt, null);
        if (result == null) {
          fRequestMonitor.cancel();
        } else if (result instanceof String) {
          fRequestMonitor.setData((String) result);
        } else {
          fRequestMonitor.setStatus(NO_CORE_STATUS);
        }
      } catch (CoreException e) {
        fRequestMonitor.setStatus(NO_CORE_STATUS);
      }
      fRequestMonitor.done();

      return Status.OK_STATUS;
    }
 @Override
 public void getAvailableFormats(IFormattedDataDMContext dmc, DataRequestMonitor<String[]> rm) {
   rm.setData(AVAILABLE_FORMATS);
   rm.done();
 }
 /**
  * Tests whether the given element matches the given expression.
  *
  * @param element Element to test against the given expression.
  * @param expression Expression to use to check if the element is matching.
  * @param rm The request monitor for the result.
  */
 @ConfinedToDsfExecutor("#getSession#getExecutor")
 protected void testElementForExpression(
     Object element, IExpression expression, final DataRequestMonitor<Boolean> rm) {
   rm.setData(false);
   rm.done();
 }
示例#18
0
    @Override
    public <V extends ICommandResult> ICommandToken queueCommand(
        final ICommand<V> command, DataRequestMonitor<V> rm) {

      final ICommandToken token =
          new ICommandToken() {
            @Override
            public ICommand<? extends ICommandResult> getCommand() {
              return command;
            }
          };

      // The class does not buffer commands itself, but sends them directly to the real
      // MICommandControl service.  Therefore, we must immediately tell our calling cache that the
      // command
      // has been sent, since we can never cancel it.
      processCommandSent(token);

      if (command instanceof MIMetaGetCPUInfo) {
        @SuppressWarnings("unchecked")
        final DataRequestMonitor<MIMetaGetCPUInfoInfo> drm =
            (DataRequestMonitor<MIMetaGetCPUInfoInfo>) rm;
        final ICommandControlDMContext dmc = (ICommandControlDMContext) command.getContext();

        if (fBackend.getSessionType() == SessionType.REMOTE) {
          // Ask GDB to fetch /proc/cpuinfo from the remote target, and then we parse it.
          String remoteFile = "/proc/cpuinfo"; // $NON-NLS-1$
          final String localFile =
              sTempFolder + "proc.cpuinfo." + getSession().getId(); // $NON-NLS-1$
          fCommandControl.queueCommand(
              fCommandFactory.createCLIRemoteGet(dmc, remoteFile, localFile),
              new ImmediateDataRequestMonitor<MIInfo>(rm) {
                @Override
                protected void handleSuccess() {
                  ICoreInfo[] info = new CoreList(localFile).getCoreList();
                  // Now that we processed the file, remove it to avoid polluting the file system
                  new File(localFile).delete();
                  drm.done(new MIMetaGetCPUInfoInfo(info));
                  processCommandDone(token, drm.getData());
                }

                @Override
                protected void handleError() {
                  // On some older linux versions, gdbserver is not able to read from /proc
                  // because it is a pseudo filesystem.
                  // We need to find some other method of getting the info we need.

                  // For a remote session, we can use GDB's -list-thread-groups --available
                  // command, which shows on which cores a process is running.  This does
                  // not necessarily give the exhaustive list of cores, but that is the best
                  // we have in this case.
                  //
                  // In this case, we don't have knowledge about CPUs, so we lump all cores
                  // into a single CPU.

                  fCommandControl.queueCommand(
                      fCommandFactory.createMIListThreadGroups(dmc, true),
                      new ImmediateDataRequestMonitor<MIListThreadGroupsInfo>(drm) {
                        @Override
                        protected void handleSuccess() {
                          // First extract the string id for every core GDB reports
                          Set<String> coreIds = new HashSet<String>();
                          IThreadGroupInfo[] groups = getData().getGroupList();
                          for (IThreadGroupInfo group : groups) {
                            coreIds.addAll(Arrays.asList(group.getCores()));
                          }

                          // Now create the context for each distinct core
                          //
                          // We don't have CPU info in this case so let's put them all under a
                          // single CPU
                          final String defaultCPUId = "0"; // $NON-NLS-1$
                          ICoreInfo[] info = new ICoreInfo[coreIds.size()];
                          int i = 0;
                          for (String id : coreIds) {
                            info[i++] = new CoreInfo(id, defaultCPUId);
                          }
                          drm.done(new MIMetaGetCPUInfoInfo(info));
                          processCommandDone(token, drm.getData());
                        }
                      });
                }
              });
        } else {
          // For a local session, parse /proc/cpuinfo directly.
          ICoreInfo[] info = new CoreList("/proc/cpuinfo").getCoreList(); // $NON-NLS-1$
          drm.done(new MIMetaGetCPUInfoInfo(info));
          processCommandDone(token, drm.getData());
        }
      } else {
        rm.setStatus(
            new Status(
                IStatus.ERROR,
                GdbPlugin.PLUGIN_ID,
                IDsfStatusConstants.INTERNAL_ERROR,
                "Unexpected Meta command",
                null)); //$NON-NLS-1$
        rm.done();
      }
      return token;
    }
 @Override
 public void getFormattedExpressionValue(
     FormattedValueDMContext dmc, DataRequestMonitor<FormattedValueDMData> rm) {
   rm.setData(new FormattedValueDMData(dmc.getFormatID()));
   rm.done();
 }
示例#20
0
  /**
   * This method processes "load info" requests. The load is computed using a sampling method; two
   * readings of a local or remote /proc/stat file are done with a delay in between. Then the load
   * is computed from the two samples, for all CPUs/cores known in the system.
   *
   * <p>Because of the method used, it's possible that fast variations in CPU usage will be missed.
   * However longer load trends should be reflected in the results.
   *
   * <p>To avoid generating too much load in the remote case, there is a cache that will return the
   * already computed load, if requested multiple times in a short period. There is also a mechanism
   * to queue subsequent requests if one is ongoing. Upon completion of the ongoing request, any
   * queued request is answered with the load that was just computed.
   *
   * @since 4.2
   */
  @Override
  public void getLoadInfo(final IDMContext context, final DataRequestMonitor<ILoadInfo> rm) {
    if (!(context instanceof ICoreDMContext) && !(context instanceof ICPUDMContext)) {
      // we only support getting the load for a CPU or a core
      rm.done(
          new Status(
              IStatus.ERROR,
              GdbPlugin.PLUGIN_ID,
              INVALID_HANDLE,
              "Load information not supported for this context type",
              null)); //$NON-NLS-1$
      return;
    }

    // The measurement interval should be of a minimum length to be meaningful
    assert (LOAD_SAMPLE_DELAY >= 100);
    // so the cache is useful
    assert (LOAD_CACHE_LIFETIME >= LOAD_SAMPLE_DELAY);

    // This way of computing the CPU load is only applicable to Linux
    if (!supportsProcPseudoFS()) {
      rm.done(
          new Status(
              IStatus.ERROR,
              GdbPlugin.PLUGIN_ID,
              NOT_SUPPORTED,
              "Operation not supported",
              null)); //$NON-NLS-1$
      return;
    }

    // Is a request is already ongoing?
    if (fLoadRequestOngoing) {
      // queue current new request
      fLoadInfoRequestCache.put(context, rm);
      return;
    }
    // no request ongoing, so proceed
    fLoadRequestOngoing = true;

    // caching mechanism to keep things sane, even if the views(s)
    // request load information very often.
    long currentTime = System.currentTimeMillis();

    // time to fetch fresh load information?
    if (fLastCpuLoadRefresh + LOAD_CACHE_LIFETIME < currentTime) {
      fLastCpuLoadRefresh = currentTime;
    } else {
      // not time yet... re-use cached load data
      processLoads(context, rm, fCachedLoads);
      fLoadRequestOngoing = false;
      return;
    }

    final ProcStatParser procStatParser = new ProcStatParser();
    final ICommandControlDMContext dmc =
        DMContexts.getAncestorOfType(context, ICommandControlDMContext.class);
    final String statFile = "/proc/stat"; // $NON-NLS-1$
    final String localFile = sTempFolder + "proc.stat." + getSession().getId(); // $NON-NLS-1$

    // Remote debugging? We will ask GDB to get us the /proc/stat file from target, twice, with a
    // delay between.
    if (fBackend.getSessionType() == SessionType.REMOTE) {
      fCommandControl.queueCommand(
          fCommandFactory.createCLIRemoteGet(dmc, statFile, localFile),
          new ImmediateDataRequestMonitor<MIInfo>(rm) {
            @Override
            protected void handleCompleted() {
              if (!isSuccess()) {
                fLoadRequestOngoing = false;
                rm.done(
                    new Status(
                        IStatus.ERROR,
                        GdbPlugin.PLUGIN_ID,
                        INTERNAL_ERROR,
                        "Can't get load info for CPU",
                        null)); //$NON-NLS-1$
                return;
              }

              // Success - parse first set of stat counters
              try {
                procStatParser.parseStatFile(localFile);
              } catch (Exception e) {
                rm.done(
                    new Status(
                        IStatus.ERROR,
                        GdbPlugin.PLUGIN_ID,
                        INTERNAL_ERROR,
                        "Can't get load info for CPU",
                        null)); //$NON-NLS-1$
                fLoadRequestOngoing = false;
                return;
              }
              // delete temp file
              new File(localFile).delete();

              getExecutor()
                  .schedule(
                      new Runnable() {
                        @Override
                        public void run() {
                          fCommandControl.queueCommand(
                              fCommandFactory.createCLIRemoteGet(dmc, statFile, localFile),
                              new ImmediateDataRequestMonitor<MIInfo>(rm) {
                                @Override
                                protected void handleCompleted() {
                                  if (!isSuccess()) {
                                    fLoadRequestOngoing = false;
                                    rm.done(
                                        new Status(
                                            IStatus.ERROR,
                                            GdbPlugin.PLUGIN_ID,
                                            INTERNAL_ERROR,
                                            "Can't get load info for CPU",
                                            null)); //$NON-NLS-1$
                                    return;
                                  }

                                  // Success - parse the second set of stat counters and compute
                                  // loads
                                  try {
                                    procStatParser.parseStatFile(localFile);
                                  } catch (Exception e) {
                                    rm.done(
                                        new Status(
                                            IStatus.ERROR,
                                            GdbPlugin.PLUGIN_ID,
                                            INTERNAL_ERROR,
                                            "Can't get load info for CPU",
                                            null)); //$NON-NLS-1$
                                    fLoadRequestOngoing = false;
                                    return;
                                  }
                                  // delete temp file
                                  new File(localFile).delete();

                                  // Compute load
                                  fCachedLoads = procStatParser.getCpuLoad();
                                  processLoads(context, rm, fCachedLoads);

                                  // done with request
                                  fLoadRequestOngoing = false;
                                  // process any queued request
                                  for (Entry<IDMContext, DataRequestMonitor<ILoadInfo>> e :
                                      fLoadInfoRequestCache.entrySet()) {
                                    processLoads(e.getKey(), e.getValue(), fCachedLoads);
                                  }
                                  fLoadInfoRequestCache.clear();
                                }
                              });
                        }
                      },
                      LOAD_SAMPLE_DELAY,
                      TimeUnit.MILLISECONDS);
            }
          });
      // Local debugging?  Then we can read /proc/stat directly
    } else {
      // Read /proc/stat file for the first time
      try {
        procStatParser.parseStatFile(statFile);
      } catch (Exception e) {
        rm.done(
            new Status(
                IStatus.ERROR,
                GdbPlugin.PLUGIN_ID,
                INTERNAL_ERROR,
                "Can't get load info for CPU",
                null)); //$NON-NLS-1$
        fLoadRequestOngoing = false;
        return;
      }

      // Read /proc/stat file again after a delay
      getExecutor()
          .schedule(
              new Runnable() {
                @Override
                public void run() {
                  try {
                    procStatParser.parseStatFile(statFile);
                  } catch (Exception e) {
                    rm.done(
                        new Status(
                            IStatus.ERROR,
                            GdbPlugin.PLUGIN_ID,
                            INTERNAL_ERROR,
                            "Can't get load info for CPU",
                            null)); //$NON-NLS-1$
                    fLoadRequestOngoing = false;
                    return;
                  }
                  // compute load
                  fCachedLoads = procStatParser.getCpuLoad();
                  processLoads(context, rm, fCachedLoads);

                  // done with request
                  fLoadRequestOngoing = false;
                  // process any queued request
                  for (Entry<IDMContext, DataRequestMonitor<ILoadInfo>> e :
                      fLoadInfoRequestCache.entrySet()) {
                    processLoads(e.getKey(), e.getValue(), fCachedLoads);
                  }
                  fLoadInfoRequestCache.clear();
                }
              },
              LOAD_SAMPLE_DELAY,
              TimeUnit.MILLISECONDS);
    }
  }