Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

[Bug] DefaultMQPushConsumer.shutdown() never stops the pop consume service, so its non-daemon threads keep the JVM alive

Aperta Adatta ai principianti
#11,427 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@iloveeyjafjalla ci sta già lavorando.

Dal 14/10/2026.

  • #11428 di @iloveeyjafjalla — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
65/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
java
Ambito
backend

Direzione di ricerca

Inizia da client/.../impl/consumer/DefaultMQPushConsumerImpl.java: il normale percorso di shutdown intorno alla riga 908 ferma solo consumeMessageService, e il ramo di avvio fallito intorno alle righe 991-993 fa lo stesso. Aggiungi una chiamata di shutdown a consumeMessagePopService in entrambi i punti, seguendo il servizio non-pop. È completato quando DefaultMQPushConsumerImplTest, usando il consumeMessagePopService mockato e testShutdown, verifica che lo shutdown del servizio pop venga chiamato. Controlla prima i due commenti, perché chi ha segnalato il problema dice di voler aprire lui stesso la PR.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Before Creating the Bug Report
  • I found a bug, not just asking a question, which should be created in GitHub Discussions.
  • I have searched the GitHub Issues and GitHub Discussions of this repository and believe that this is not a duplicate.
  • I have confirmed that this bug belongs to the current repository, not other repositories of RocketMQ.
Runtime platform environment

OS: any (client side, DefaultMQPushConsumer)

RocketMQ version

branch: develop
Git commit id: a7edeecfb

JDK Version

Compiler: Temurin 1.8.0_504 (target 1.8, same as CI)

Describe the Bug

DefaultMQPushConsumerImpl.start() creates and starts two consume services, but shutdown() stops only the first one:

this.consumeMessageService.start();
// POPTODO
this.consumeMessagePopService.start();       // DefaultMQPushConsumerImpl.java:984-986
case RUNNING:
    this.consumeMessageService.shutdown(awaitTerminateMillis);      // :908 — the pop service is never stopped

The pop service is not idle after it is started: ConsumeMessagePopOrderlyService.start() schedules lockMQPeriodically() at a fixed rate on a single-thread executor created with new ThreadFactoryImpl("ConsumeMessageScheduledThread_") (client/.../ConsumeMessagePopOrderlyService.java:64-77), and ThreadFactoryImpl creates non-daemon threads by default (common/.../ThreadFactoryImpl.java:35, :59). ConsumeMessagePopConcurrentlyService.start() likewise starts its consume executor. Both services implement shutdown(long) (ConsumeMessagePopOrderlyService.java:80-88, ConsumeMessagePopConcurrentlyService.java:70), and no code in the client module ever calls it — the only references to the field are the two assignments, start() and submitPopConsumeRequest.

The same omission exists in the failed-start branch, which stops only consumeMessageService when the consumer group is already registered (DefaultMQPushConsumerImpl.java:991-993).

Steps to Reproduce
  1. DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group"); consumer.subscribe("topic", "*"); consumer.registerMessageListener(listener);
  2. consumer.start(); consumer.shutdown();
  3. The pop service is still running: for CLUSTERING (the default) the ConsumeMessageScheduledThread_ thread keeps firing lockMQPeriodically() every REBALANCE_LOCK_INTERVAL on an empty process-queue table, the threads are non-daemon, so a JVM that relies on the consumer's shutdown to release its resources never terminates.

At the unit level the existing harness covers it: DefaultMQPushConsumerImplTest already injects a mocked consumeMessagePopService (line ~250-254) and has a testShutdown, so asserting that the service is shut down with shutdown() fails deterministically today.

What Did You Expect to See?

DefaultMQPushConsumer.shutdown() "shut down this client and releasing underlying resources" (client/.../consumer/DefaultMQPushConsumer.java:789) — i.e. both consume services are stopped, exactly like the non-pop one in the same method. The pop services' own shutdown(long) methods are the proof that this was the intent.

What Did You See Instead?

After shutdown() the consumer's pop scheduler (and, for pop consumers, the pop consume executor) keeps running with non-daemon threads; the client appears stopped (serviceState = SHUTDOWN_ALREADY) while resources are still held, which can leave the JVM unable to exit.

Additional Context

Minimal fix: stop consumeMessagePopService next to consumeMessageService in both places — the normal shutdown path and the register-failure path.

I will open a PR with those two one-line changes plus a regression test in DefaultMQPushConsumerImplTest (red before: the pop service receives no shutdown call).

Lingua principale
Java
Stelle
22.6k
Fork
12k
Merge medio
7g 15h
PR unite (30g)
15

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di apache/rocketmq

Tutte le issue di apache/rocketmq

Issue simili

Altre issue su Java

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.