Procházet zdrojové kódy

fix(files): files may be closed for multiple times

greatbridf před 2 roky
rodič
revize
3b78bb6760
2 změnil soubory, kde provedl 35 přidání a 29 odebrání
  1. 33 29
      include/kernel/process.hpp
  2. 2 0
      src/kernel/process.cpp

+ 33 - 29
include/kernel/process.hpp

@@ -149,17 +149,34 @@ public:
     class filearr {
     public:
         using container_type = types::list<fs::file>;
-        using array_type = types::hash_map<int, container_type::iterator_type, types::linux_hasher<size_t>>;
+        using array_type = types::map<int, container_type::iterator_type>;
 
     private:
-        inline static container_type* files = nullptr;
+        inline static container_type* files;
         array_type arr;
         int next_fd = 0;
 
+    public:
+        inline static void init_global_file_container(void)
+        {
+            files = types::pnew<types::kernel_allocator>(files);
+        }
+
+    private:
+        // iter should not be nullptr
+        constexpr void _close(container_type::iterator_type iter)
+        {
+            if (iter->ref == 1)
+                files->erase(iter);
+            else
+                --iter->ref;
+        }
+
     public:
         constexpr filearr(const filearr&) = delete;
         constexpr filearr& operator=(const filearr&) = delete;
         constexpr filearr& operator=(filearr&&) = delete;
+        constexpr filearr(void) = default;
         constexpr filearr(filearr&& val)
             : arr { types::move(val.arr) }
             , next_fd { val.next_fd }
@@ -167,12 +184,6 @@ public:
             val.next_fd = 0;
         }
 
-        explicit filearr()
-        {
-            if (!files)
-                files = types::pnew<types::kernel_allocator>(files);
-        }
-
         constexpr void dup(const filearr& orig)
         {
             if (this->next_fd)
@@ -180,13 +191,9 @@ public:
 
             this->next_fd = orig.next_fd;
 
-            for (int i = 0; i < this->next_fd; ++i) {
-                auto iter = orig.arr.find(i);
-                if (!iter)
-                    continue;
-
-                this->arr.emplace(iter->key, iter->value);
-                ++iter->value->ref;
+            for (auto iter : orig.arr) {
+                this->arr.insert(types::make_pair(iter.key, iter.value));
+                ++iter.value->ref;
             }
         }
 
@@ -230,31 +237,28 @@ public:
                 1 });
 
             int fd = next_fd++;
-            arr.emplace(fd, iter);
+            arr.insert(types::make_pair(fd, iter));
             return fd;
         }
 
-        // close file descriptor
-        // where iter is guaranteed not nullptr
-        constexpr void close(array_type::iterator_type iter)
+        constexpr void close(int fd)
         {
-            if (iter->value->ref == 1)
-                files->erase(iter->value);
-            else
-                --iter->value->ref;
+            auto iter = arr.find(fd);
+            if (iter) {
+                _close(iter->value);
+                arr.erase(iter);
+            }
         }
 
-        constexpr void close(int fd)
+        constexpr void close_all(void)
         {
-            auto iter = arr.find(fd);
-            if (iter)
-                close(iter);
+            for (auto iter : this->arr)
+                close(iter.key);
         }
 
         constexpr ~filearr()
         {
-            for (int i = 0; i < next_fd; ++i)
-                close(i);
+            close_all();
         }
     };
 

+ 2 - 0
src/kernel/process.cpp

@@ -210,6 +210,8 @@ void NORETURN init_scheduler(void)
     procs = types::pnew<types::kernel_allocator>(procs);
     readythds = types::pnew<types::kernel_allocator>(readythds);
 
+    process::filearr::init_global_file_container();
+
     // init process has no parent
     auto* init = &procs->emplace(0)->value;
     init->files.open("/dev/console", 0);