{"record":{"id":"c0b4dc6da35e12a6","repo":"apache/hadoop","slug":"thread-aborted","errorCode":null,"errorMessage":"Thread aborted","messagePattern":"Thread aborted","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-tools/hadoop-distcp/src/main/java/org/apache/hadoop/tools/util/ThrottledInputStream.java","lineNumber":104,"sourceCode":"  public int read(byte[] b, int off, int len) throws IOException {\n    if (len == 0) {\n      return 0;\n    }\n    throttle();\n    int readLen = rawStream.read(b, off, len);\n    if (readLen != -1) {\n      bytesRead += readLen;\n    }\n    return readLen;\n  }\n\n  private void throttle() throws IOException {\n    while (getBytesPerSec() > maxBytesPerSec) {\n      try {\n        Thread.sleep(SLEEP_DURATION_MS);\n        totalSleepTime += SLEEP_DURATION_MS;\n      } catch (InterruptedException e) {\n        throw new IOException(\"Thread aborted\", e);\n      }\n    }\n  }\n\n  /**\n   * Getter for the number of bytes read from this stream, since creation.\n   * @return The number of bytes.\n   */\n  public long getTotalBytesRead() {\n    return bytesRead;\n  }\n\n  /**\n   * Getter for the read-rate from this stream, since creation.\n   * Calculated as bytesRead/elapsedTimeSinceStart.\n   * @return Read rate, in bytes/sec.\n   */\n  public long getBytesPerSec() {","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-tools/hadoop-distcp/src/main/java/org/apache/hadoop/tools/util/ThrottledInputStream.java#L86-L122","documentation":"ThrottledInputStream.throttle() sleeps in a loop whenever the observed transfer rate exceeds the cap (set by -bandwidth / distcp.map.bandwidth.mb). If the reading thread is interrupted during that sleep, the InterruptedException is converted to IOException(\"Thread aborted\", e). It signals the MapReduce task was cancelled or killed mid-read, not a data problem.","triggerScenarios":"The MR task attempt is killed by the framework (preemption, speculative-execution loser, job kill/abort) while the throttled stream was sleeping in throttle(); externally interrupting a thread that reads through ThrottledInputStream in library usage.","commonSituations":"Operator-cancelled jobs; YARN preemption; speculative tasks being stopped late; test harnesses interrupting worker threads.","solutions":["Treat it as a cancellation signal: check JobHistory/ApplicationMaster logs for why the attempt was killed","No data repair needed: the framework retries live attempts; re-run the job if it was externally killed","If embedding ThrottledInputStream, catch the IOException and restore the interrupt flag via Thread.currentThread().interrupt()","Do not manually interrupt threads that own filesystem streams"],"exampleFix":"// before: interrupt status silently swallowed\ntry {\n  while ((n = throttledIn.read(buf)) != -1) { /* write */ }\n} catch (IOException e) {\n  log.error(\"copy failed\", e);\n}\n\n// after: honour cancellation\ntry {\n  while ((n = throttledIn.read(buf)) != -1) { /* write */ }\n} catch (IOException e) {\n  if (e.getCause() instanceof InterruptedException) {\n    Thread.currentThread().interrupt();   // preserve cancellation\n  } else {\n    throw e;\n  }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (IOException e) {\n  if (e.getCause() instanceof InterruptedException) {\n    Thread.currentThread().interrupt();  // propagate cancellation correctly\n  } else {\n    throw e;\n  }\n}","preventionTips":["Never interrupt threads that own filesystem streams; cancel at the job level instead","Check AM/JobHistory logs for preemption or kills before debugging data paths","Restore the interrupt flag when this IOException surfaces in embedded usage"],"tags":["distcp","hadoop","bandwidth","throttling","interruption"],"backgroundTag":"thread-interrupted","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}