{"record":{"id":"021a6ee83b6b115a","repo":"apache/hadoop","slug":"threadjoin-pthread-join-failed-with-error-d","errorCode":null,"errorMessage":"threadJoin: pthread_join failed with error %d\n","messagePattern":"threadJoin: pthread_join failed with error (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfs/os/posix/thread.c","lineNumber":49,"sourceCode":"static void* runThread(void *toRun) {\n  const thread *t = toRun;\n  t->start(t->arg);\n  return NULL;\n}\n\nint threadCreate(thread *t) {\n  int ret;\n  ret = pthread_create(&t->id, NULL, runThread, t);\n  if (ret) {\n    fprintf(stderr, \"threadCreate: pthread_create failed with error %d\\n\", ret);\n  }\n  return ret;\n}\n\nint threadJoin(const thread *t) {\n  int ret = pthread_join(t->id, NULL);\n  if (ret) {\n    fprintf(stderr, \"threadJoin: pthread_join failed with error %d\\n\", ret);\n  }\n  return ret;\n}\n","sourceCodeStart":31,"sourceCodeEnd":53,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfs/os/posix/thread.c#L31-L53","documentation":"threadJoin() wraps pthread_join; failure codes are ESRCH (no such thread — already joined or handle reused), EINVAL (thread not joinable, e.g. detached), EDEADLK (thread joining itself). After this error the thread's state is undefined; joining an already-reaped thread id risks reaping an unrelated, reused thread id.","triggerScenarios":"Calling threadJoin twice on the same handle; joining a thread that was detached elsewhere; racing threadCreate reuse of the same thread struct before the join completes.","commonSituations":"Cleanup loops that join every thread including ones already joined in an error branch; refactors that introduce detach; stress tests recycling thread structs.","solutions":["Audit for double-join: after a successful join, invalidate the handle and never join it again","If EINVAL, find who detached the thread and pick one ownership model (join OR detach, never both)","If EDEADLK, restructure shutdown so a thread never joins itself","Wrap joins in a helper that clears the stored id, making double-join impossible"],"exampleFix":"/* before */\nthreadJoin(&t);\n/* error path may join the same t again */\n\n/* after: join exactly once, then invalidate */\nint ret = threadJoin(&t);\nt.id = 0;  /* mark joined */\nif (ret) log_join_error(ret);","handlingStrategy":"validation","validationCode":"typedef struct { thread t; int joined; } thread_once;\n\nstatic int join_once(thread_once *w) {\n    if (w->joined) return 0;   /* block double-join at the source */\n    w->joined = 1;\n    return threadJoin(&w->t);\n}","typeGuard":null,"tryCatchPattern":"int ret = threadJoin(&t);\nif (ret != 0) {\n    /* ESRCH: already joined; EINVAL: detached; handle without re-joining */\n    log_warn(\"join failed code=%d\", ret);\n}","preventionTips":["Invalidate thread handles right after a successful join","Choose one ownership model per thread: joinable or detached, never both","Never join the running thread itself"],"tags":["libhdfs","pthread","thread-join","posix","double-join"],"backgroundTag":"pthread-join-failed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}