{"record":{"id":"5e68b8944dd2c5fd","repo":"LMAX-Exchange/disruptor","slug":"already-running","errorCode":null,"errorMessage":"Already running","messagePattern":"Already running","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/perftest/java/com/lmax/disruptor/support/MultiBufferBatchEventProcessor.java","lineNumber":49,"sourceCode":"        }\n\n        this.providers = providers;\n        this.barriers = barriers;\n        this.handler = handler;\n\n        this.sequences = new Sequence[providers.length];\n        for (int i = 0; i < sequences.length; i++)\n        {\n            sequences[i] = new Sequence(-1);\n        }\n    }\n\n    @Override\n    public void run()\n    {\n        if (!isRunning.compareAndSet(false, true))\n        {\n            throw new RuntimeException(\"Already running\");\n        }\n\n        for (SequenceBarrier barrier : barriers)\n        {\n            barrier.clearAlert();\n        }\n\n        final int barrierLength = barriers.length;\n\n        while (true)\n        {\n            try\n            {\n                for (int i = 0; i < barrierLength; i++)\n                {\n                    long available = barriers[i].waitFor(-1);\n                    Sequence sequence = sequences[i];\n","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/LMAX-Exchange/disruptor/blob/c871ca49826a6be7ada6957f6fbafcfecf7b1f87/src/perftest/java/com/lmax/disruptor/support/MultiBufferBatchEventProcessor.java#L31-L67","documentation":"RuntimeException thrown by MultiBufferBatchEventProcessor.run (src/perftest/java/com/lmax/disruptor/support/MultiBufferBatchEventProcessor.java:49) when run() is entered while the processor is already running. The processor guards its single-consumer loop with an AtomicBoolean compareAndSet(false, true); a second concurrent invocation cannot acquire it. Note this class is a perftest support utility, not the production DSL path.","triggerScenarios":"Submitting the same MultiBufferBatchEventProcessor instance to an executor twice (e.g. two executor.submit(processor) calls), or calling run() directly on a thread while it is already executing. Also restarting the processor by calling run() again without the previous loop having exited after halt() (halt() sets isRunning false, so a genuine restart works only after the old loop has observed the alert and returned).","commonSituations":"Porting the multi-buffer perftest pattern into application code and wiring the processor into a ScheduledExecutorService that re-runs tasks, causing overlapping executions; a supervisor/health-check loop that 'restarts' consumers by calling run() while the old thread is still inside the while(true) loop; copy-pasting benchmark scaffolding where the processor instance is a shared field.","solutions":["Run exactly one thread per processor instance: create a fresh MultiBufferBatchEventProcessor (or submit the single instance once) instead of resubmitting it.","If restarting after halt(), first join/interrupt the old thread and confirm processor.isRunning() == false before calling run() again.","If the executor may re-run tasks, wrap the processor in a dedicated Thread created per lifecycle rather than passing the processor itself as a repeating Runnable.","For production use, prefer the supported DSL (Disruptor / BatchEventProcessor / WorkerPool) instead of this perftest support class, since it lacks the lifecycle management of the main library."],"exampleFix":"// before: same instance submitted twice -> second run() throws \"Already running\"\nexecutor.submit(processor);\nexecutor.submit(processor); // RuntimeException\n\n// after: one instance per run, wait for shutdown before restarting\nexecutor.submit(processor);\n// ... to restart later:\nprocessor.halt();\nwhile (processor.isRunning()) { Thread.onSpinWait(); }\nexecutor.submit(new MultiBufferBatchEventProcessor<>(providers, barriers, handler));","handlingStrategy":"validation","validationCode":"// Before (re)submitting the processor, check its lifecycle state\nif (processor.isRunning()) {\n    throw new IllegalStateException(\"MultiBufferBatchEventProcessor is already running; halt it and wait for exit before restarting\");\n}\nexecutor.submit(processor);","typeGuard":null,"tryCatchPattern":"try {\n    executor.submit(processor);\n} catch (RuntimeException e) {\n    if (\"Already running\".equals(e.getMessage())) {\n        log.warn(\"Processor already running; skipping duplicate start\");\n    } else {\n        throw e;\n    }\n}","preventionTips":["Own the lifecycle: submit each EventProcessor instance to exactly one thread and never reuse the instance as a repeating task.","On restart, call halt() and wait until isRunning() returns false (join the old thread) before invoking run() again.","Keep application logic on the production DSL (Disruptor/BatchEventProcessor/WorkerPool) rather than perftest support classes with hand-rolled lifecycle guards."],"tags":["java","disruptor","concurrency","lifecycle","perftest"],"backgroundTag":null,"analyzedSha":"c871ca49826a6be7ada6957f6fbafcfecf7b1f87","analyzedAt":"2026-08-14T14:22:36.358Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}