diff --git a/servlet/src/main/java/io/undertow/servlet/core/ManagedFilter.java b/servlet/src/main/java/io/undertow/servlet/core/ManagedFilter.java
index 8e074d8de..79b81f303 100644
--- a/servlet/src/main/java/io/undertow/servlet/core/ManagedFilter.java
+++ b/servlet/src/main/java/io/undertow/servlet/core/ManagedFilter.java
@@ -19,6 +19,7 @@
 package io.undertow.servlet.core;
 
 import java.io.IOException;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
@@ -34,6 +35,8 @@ import io.undertow.servlet.api.InstanceHandle;
 import io.undertow.servlet.spec.FilterConfigImpl;
 import io.undertow.servlet.spec.ServletContextImpl;
 
+import static org.xnio.Bits.anyAreSet;
+
 /**
  * @author Stuart Douglas
  */
@@ -42,7 +45,14 @@ public class ManagedFilter implements Lifecycle {
     private final FilterInfo filterInfo;
     private final ServletContextImpl servletContext;
 
-    private volatile boolean started = false;
+    private static final int FLAG_STARTED = 1;
+    private static final int FLAG_STOPPED = 1 << 1;
+    @SuppressWarnings("unused")
+    private volatile int state;
+    private static final AtomicIntegerFieldUpdater<ManagedFilter> stateFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(ManagedFilter.class, "state");
+    /*private volatile boolean started = false;
+    private volatile boolean stopped = false;*/
+
     private volatile Filter filter;
     private volatile InstanceHandle<? extends Filter> handle;
 
@@ -55,9 +65,7 @@ public class ManagedFilter implements Lifecycle {
         if(servletContext.getDeployment().getDeploymentState() != DeploymentManager.State.STARTED) {
             throw UndertowServletMessages.MESSAGES.deploymentStopped(servletContext.getDeployment().getDeploymentInfo().getDeploymentName());
         }
-        if (!started) {
-            start();
-        }
+        start();
         getFilter().doFilter(request, response, chain);
     }
 
@@ -83,30 +91,33 @@ public class ManagedFilter implements Lifecycle {
         }
     }
 
-    public synchronized void start() throws ServletException {
-        if (!started) {
-
-            started = true;
-        }
+    public void start() throws ServletException {
+        do {
+            if (anyAreSet(stateFieldUpdater.get(this), FLAG_STOPPED)) {
+                throw UndertowServletMessages.MESSAGES.deploymentStopped(servletContext.getDeployment().getDeploymentInfo().getDeploymentName());
+            }
+        } while (stateFieldUpdater.get(this) != FLAG_STARTED && !stateFieldUpdater.compareAndSet(this, 0, FLAG_STARTED));
     }
 
-    public synchronized void stop() {
-        started = false;
-        if (handle != null) {
-            try {
-                new LifecyleInterceptorInvocation(servletContext.getDeployment().getDeploymentInfo().getLifecycleInterceptors(), filterInfo, filter).proceed();
-            } catch (Exception e) {
-                UndertowServletLogger.ROOT_LOGGER.failedToDestroy(filterInfo, e);
+    public void stop() {
+        stateFieldUpdater.set(this, FLAG_STOPPED);
+        synchronized (this) {
+            if (handle != null) {
+                try {
+                    new LifecyleInterceptorInvocation(servletContext.getDeployment().getDeploymentInfo().getLifecycleInterceptors(), filterInfo, filter).proceed();
+                } catch (Exception e) {
+                    UndertowServletLogger.ROOT_LOGGER.failedToDestroy(filterInfo, e);
+                }
+                handle.release();
             }
-            handle.release();
+            filter = null;
+            handle = null;
         }
-        filter = null;
-        handle = null;
     }
 
     @Override
     public boolean isStarted() {
-        return started;
+        return anyAreSet(state, FLAG_STARTED);
     }
 
     public FilterInfo getFilterInfo() {
diff --git a/servlet/src/test/java/io/undertow/servlet/test/defaultservlet/DefaultServletTestCase.java b/servlet/src/test/java/io/undertow/servlet/test/defaultservlet/DefaultServletTestCase.java
index b920e1e71..aac68d6db 100644
--- a/servlet/src/test/java/io/undertow/servlet/test/defaultservlet/DefaultServletTestCase.java
+++ b/servlet/src/test/java/io/undertow/servlet/test/defaultservlet/DefaultServletTestCase.java
@@ -44,6 +44,7 @@ import org.apache.http.Header;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.util.EntityUtils;
+import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -80,6 +81,9 @@ public class DefaultServletTestCase {
         builder.addFilter(new FilterInfo("date-header", GetDateFilter.class));
         builder.addFilterUrlMapping("date-header", "/*", DispatcherType.REQUEST);
 
+        // see UNDERTOW-
+        builder.addFilter(new FilterInfo("sleeping-filter", SleepingFilter.class));
+        builder.addFilterUrlMapping("sleeping-filter", "/sleepingpath/*", DispatcherType.REQUEST);
 
         builder.addFilter(new FilterInfo("Filter", HelloFilter.class));
         builder.addFilterUrlMapping("Filter", "/filterpath/*", DispatcherType.REQUEST);
@@ -91,6 +95,26 @@ public class DefaultServletTestCase {
         DefaultServer.setRootHandler(root);
     }
 
+    @AfterClass
+    public static void testGracefulShutdownWithSleepingFilter() throws IOException, InterruptedException {
+        new Thread(() -> {
+            TestHttpClient client = new TestHttpClient();
+            try {
+                HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/servletContext/sleepingpath/filtered.txt");
+                client.execute(get);
+            } catch (org.apache.http.client.ClientProtocolException e) {
+                e.printStackTrace();
+            } catch (java.io.IOException e) {
+                e.printStackTrace();
+            } finally {
+                client.getConnectionManager().shutdown();
+            }}).start();
+        Thread.sleep(50);
+        DefaultServer.stopServer();
+    }
+
+
+
     @Test
     public void testSimpleResource() throws IOException {
         TestHttpClient client = new TestHttpClient();
diff --git a/servlet/src/test/java/io/undertow/servlet/test/defaultservlet/SleepingFilter.java b/servlet/src/test/java/io/undertow/servlet/test/defaultservlet/SleepingFilter.java
new file mode 100644
index 000000000..13d922f0d
--- /dev/null
+++ b/servlet/src/test/java/io/undertow/servlet/test/defaultservlet/SleepingFilter.java
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2022 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package io.undertow.servlet.test.defaultservlet;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.io.IOException;
+
+/**
+ * @author Flavia Rainone
+ */
+public class SleepingFilter implements Filter {
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        try {
+            Thread.sleep(600 * 1000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void destroy() {
+
+    }
+}
