Fix NPEs caused by RepeatingTask initialisation race condition

This commit is contained in:
Luck 2019-12-26 20:25:14 +00:00
parent 0e64b61be4
commit 10680668db
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
4 changed files with 30 additions and 73 deletions

View File

@ -206,8 +206,8 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
public final void disable() {
// shutdown permission vault and verbose handler tasks
this.permissionRegistry.stop();
this.verboseHandler.stop();
this.permissionRegistry.close();
this.verboseHandler.close();
// unload extensions
this.extensionManager.close();

View File

@ -28,8 +28,8 @@ package me.lucko.luckperms.common.treeview;
import com.google.common.base.Splitter;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerTask;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import me.lucko.luckperms.common.util.RepeatingTask;
import java.util.List;
import java.util.Map;
@ -40,19 +40,20 @@ import java.util.concurrent.TimeUnit;
/**
* Stores a collection of all permissions known to the platform.
*/
public class PermissionRegistry extends RepeatingTask {
public class PermissionRegistry implements AutoCloseable {
private static final Splitter DOT_SPLIT = Splitter.on('.').omitEmptyStrings();
// the root node in the tree
/** The root node in the tree */
private final TreeNode rootNode;
// a queue of permission strings to be processed by the tree
/** A queue of permission strings to be added to the tree */
private final Queue<String> queue;
/** The tick task */
private final SchedulerTask task;
public PermissionRegistry(SchedulerAdapter scheduler) {
super(scheduler, 1, TimeUnit.SECONDS);
this.rootNode = new TreeNode();
this.queue = new ConcurrentLinkedQueue<>();
this.task = scheduler.asyncRepeating(this::tick, 1, TimeUnit.SECONDS);
}
public TreeNode getRootNode() {
@ -70,13 +71,17 @@ public class PermissionRegistry extends RepeatingTask {
this.queue.offer(permission);
}
@Override
protected void tick() {
private void tick() {
for (String e; (e = this.queue.poll()) != null; ) {
insert(e);
}
}
@Override
public void close() {
this.task.cancel();
}
public void insert(String permission) {
try {
doInsert(permission);

View File

@ -1,53 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.util;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerTask;
import java.util.concurrent.TimeUnit;
public abstract class RepeatingTask {
private final SchedulerTask task;
protected RepeatingTask(SchedulerAdapter scheduler, long time, TimeUnit unit) {
this.task = scheduler.asyncRepeating(this::run, time, unit);
}
private void run() {
try {
tick();
} catch (Exception e) {
e.printStackTrace();
}
}
protected abstract void tick();
public void stop() {
this.task.cancel();
}
}

View File

@ -27,8 +27,8 @@ package me.lucko.luckperms.common.verbose;
import me.lucko.luckperms.common.calculator.result.TristateResult;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerTask;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.util.RepeatingTask;
import me.lucko.luckperms.common.verbose.event.MetaCheckEvent;
import me.lucko.luckperms.common.verbose.event.PermissionCheckEvent;
import me.lucko.luckperms.common.verbose.event.VerboseEvent;
@ -45,21 +45,21 @@ import java.util.concurrent.TimeUnit;
/**
* Accepts {@link VerboseEvent}s and passes them onto registered {@link VerboseListener}s.
*/
public class VerboseHandler extends RepeatingTask {
public class VerboseHandler implements AutoCloseable {
// the listeners currently registered
/** A map of currently registered listeners */
private final Map<UUID, VerboseListener> listeners;
// a queue of events
/** A queue of verbose events to be handled */
private final Queue<VerboseEvent> queue;
// if there are any listeners currently registered
/** If there are any listeners registered */
private boolean listening = false;
/** The tick task */
private final SchedulerTask task;
public VerboseHandler(SchedulerAdapter scheduler) {
super(scheduler, 100, TimeUnit.MILLISECONDS);
this.listeners = new ConcurrentHashMap<>();
this.queue = new ConcurrentLinkedQueue<>();
this.task = scheduler.asyncRepeating(this::tick, 100, TimeUnit.MILLISECONDS);
}
/**
@ -137,8 +137,7 @@ public class VerboseHandler extends RepeatingTask {
return this.listeners.remove(uuid);
}
@Override
protected void tick() {
private void tick() {
// remove listeners where the sender is no longer valid
this.listeners.values().removeIf(l -> !l.getNotifiedSender().isValid());
@ -159,4 +158,10 @@ public class VerboseHandler extends RepeatingTask {
}
}
}
@Override
public void close() {
this.task.cancel();
}
}