Folia icon indicating copy to clipboard operation
Folia copied to clipboard

Globalregion stopped ticking sometimes

Open MrHua269 opened this issue 9 months ago • 6 comments

Stack trace

paste your stack trace or a paste.gg link here!

No stack trace was thrown even the watchdog

Plugin and Datapack List

Screenshot_20250326_005731.jpg

Actions to reproduce (if known)

No response

Folia version

Commit bb12eee2bdc68452dd643dd6e4efe8ecf68df3ce

Other

It seems that the tick threads are not blocked and the tick task of globalregion got lost.(I will provide more further information if I have time(There is actually a thread dump but it's on my computer and I cannot access it currently))

MrHua269 avatar Mar 25 '25 16:03 MrHua269

A thread dump generated by jcmd: https://pastebin.com/20xkNiGX

MrHua269 avatar Mar 25 '25 16:03 MrHua269

I've been encountering the same behavior, and I also may have confirmed that the tasks still run, I am not sure as to why, or if it's exactly this, been trying to confirm, but it seems that the global tasks still run .

PedroMPagani avatar Mar 25 '25 17:03 PedroMPagani

There's also a wrong use of variable for isWatched

Image @Spottedleaf WATCHED_HANDLE for isWatched isn't used, its using the tick

PedroMPagani avatar Mar 25 '25 17:03 PedroMPagani

Ok, I found the issue.

Image

PedroMPagani avatar Mar 25 '25 18:03 PedroMPagani

final long scheduleTime = Math.max(tick.getScheduledStart(), System.nanoTime()); This is "fixing" the issue, you can replicate the bug by copying teh entire scheduled class and running something like this:



package io.papermc.paper.threadedregions;

import java.util.*;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BooleanSupplier;

public class Main {

    public static class BenchmarkRegion extends ScheduledTaskThreadPool.SchedulableTick {

        private long lastPeriod = System.nanoTime();

        public long getLastPeriod(){
            return new Long(lastPeriod);
        }

        private final long id;

        public BenchmarkRegion(long id) {
            this.id = id;
        }

        @Override
        public String toDump() {
            return String.valueOf(id);
        }


        private boolean cleaned = false;

        public void markCleaned() {
            this.cleaned = true;
        }

        @Override
        public boolean runTick() {
            this.cleaned = false;
            lastPeriod= System.nanoTime();
            this.setScheduledStart(System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(50));
            return true;
        }



        @Override
        public boolean hasTasks() {
            return false;
        }

        @Override
        public boolean runTasks(BooleanSupplier canContinue) {
            return true;
        }

    }
    static ScheduledTaskThreadPool scheduler;
    public static void main(String[] args) {
        scheduler = new ScheduledTaskThreadPool(new ThreadFactory() {
            private final AtomicInteger idGenerator = new AtomicInteger();

            @Override
            public Thread newThread(final Runnable run) {
                final Thread ret = new Thread(run, "Region Scheduler Thread #" + this.idGenerator.getAndIncrement());
                return ret;
            }
        }, TimeUnit.MILLISECONDS.toNanos(3), TimeUnit.MILLISECONDS.toNanos(2));
        scheduler.setCoreThreads(256);
        List<BenchmarkRegion> regions = new ArrayList<>();
        for (int i = 0; i < 1024 * 16; i++) {
            BenchmarkRegion region = new BenchmarkRegion(i);
            region.setScheduledStart(System.nanoTime() + 50);
            scheduler.schedule(region);
            regions.add(region);
            scheduler.notifyTasks(region);
        }
        Scanner scanner = new Scanner(System.in);
        while (true) {
            String line = scanner.nextLine();
            if (line.equalsIgnoreCase("tps")) {
                System.out.println("TPS");
                try {
                    Optional<BenchmarkRegion> benchmarkRegion = regions.stream().min(Comparator.comparingLong(BenchmarkRegion::getLastPeriod));
                    benchmarkRegion.ifPresent(region -> System.out.println("region: " + region.id + " " + (System.nanoTime() - region.lastPeriod)/(1_000_000.0) +"ms ago. " + region.cleaned));
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
            }
        }

    }

}

PedroMPagani avatar Mar 25 '25 18:03 PedroMPagani

The new thing I found is that the globalregion gets scheduled before any worker thread started, Idk if it is causing that issue but in the older scheduler, it doesn't act like this

MrHua269 avatar Apr 05 '25 02:04 MrHua269