فهرست منبع

AK+Kernel: Handle allocation failures in Device::try_make_request

This adds try_* methods to AK::DoublyLinkedList and updates the Device
class to use those to gracefully handle allocation failures.

Refs #6369.
Gunnar Beutner 2 سال پیش
والد
کامیت
ab8b043684
2فایلهای تغییر یافته به همراه28 افزوده شده و 7 حذف شده
  1. 27 6
      AK/DoublyLinkedList.h
  2. 1 1
      Kernel/Devices/Device.h

+ 27 - 6
AK/DoublyLinkedList.h

@@ -7,6 +7,7 @@
 #pragma once
 
 #include <AK/Assertions.h>
+#include <AK/Error.h>
 #include <AK/Find.h>
 #include <AK/StdLibExtras.h>
 
@@ -91,41 +92,61 @@ public:
     }
 
     template<typename U>
-    void append(U&& value)
+    ErrorOr<void> try_append(U&& value)
     {
         static_assert(
             requires { T(value); }, "Conversion operator is missing.");
-        auto* node = new Node(forward<U>(value));
+        auto* node = new (nothrow) Node(forward<U>(value));
+        if (!node)
+            return Error::from_errno(ENOMEM);
         if (!m_head) {
             VERIFY(!m_tail);
             m_head = node;
             m_tail = node;
-            return;
+            return {};
         }
         VERIFY(m_tail);
         VERIFY(!node->next);
         m_tail->next = node;
         node->prev = m_tail;
         m_tail = node;
+        return {};
     }
 
     template<typename U>
-    void prepend(U&& value)
+    ErrorOr<void> try_prepend(U&& value)
     {
         static_assert(IsSame<T, U>);
-        auto* node = new Node(forward<U>(value));
+        auto* node = new (nothrow) Node(forward<U>(value));
+        if (!node)
+            return Error::from_errno(ENOMEM);
         if (!m_head) {
             VERIFY(!m_tail);
             m_head = node;
             m_tail = node;
-            return;
+            return {};
         }
         VERIFY(m_tail);
         VERIFY(!node->prev);
         m_head->prev = node;
         node->next = m_head;
         m_head = node;
+        return {};
+    }
+
+#ifndef KERNEL
+    template<typename U>
+    void append(U&& value)
+    {
+        MUST(try_append(forward<U>(value)));
+    }
+
+    template<typename U>
+    void prepend(U&& value)
+    {
+        MUST(try_prepend(forward<U>(value)));
     }
+#endif
 
     [[nodiscard]] bool contains_slow(const T& value) const
     {

+ 1 - 1
Kernel/Devices/Device.h

@@ -58,7 +58,7 @@ public:
         auto request = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) AsyncRequestType(*this, forward<Args>(args)...)));
         SpinlockLocker lock(m_requests_lock);
         bool was_empty = m_requests.is_empty();
-        m_requests.append(request);
+        TRY(m_requests.try_append(request));
         if (was_empty)
             request->do_start(move(lock));
         return request;