From c2dc5adbe7c4e2ff7701da03f58d7dc74247e084 Mon Sep 17 00:00:00 2001 From: nakst <> Date: Sat, 13 Nov 2021 19:33:44 +0000 Subject: [PATCH] fix race on desktopProcess in shut down --- desktop/api.cpp | 2 +- desktop/desktop.cpp | 11 +++++---- desktop/os.header | 1 - drivers/acpica.cpp | 5 ++-- kernel/cache.cpp | 2 ++ kernel/drivers.cpp | 24 +++++++++---------- kernel/files.cpp | 27 +++++++++++----------- kernel/graphics.cpp | 8 +++---- kernel/memory.cpp | 1 - kernel/objects.cpp | 10 ++++---- kernel/scheduler.cpp | 47 +++++++++++++++++++++++++++++++------- kernel/synchronisation.cpp | 5 +--- kernel/syscall.cpp | 14 ++++++------ kernel/windows.cpp | 28 +++++++++++------------ 14 files changed, 106 insertions(+), 79 deletions(-) diff --git a/desktop/api.cpp b/desktop/api.cpp index 9e37a0d..12f1e42 100644 --- a/desktop/api.cpp +++ b/desktop/api.cpp @@ -1483,7 +1483,7 @@ extern "C" void _start(EsProcessStartupInformation *_startupInformation) { while (!api.foundBootFileSystem) { EsMessage *message = EsMessageReceive(); - DesktopMessage(message); + DesktopSendMessage(message); } size_t fileSize; diff --git a/desktop/desktop.cpp b/desktop/desktop.cpp index c62dbcd..dd2cdea 100644 --- a/desktop/desktop.cpp +++ b/desktop/desktop.cpp @@ -238,6 +238,7 @@ void WallpaperLoad(EsGeneric); WindowTab *WindowTabCreate(ContainerWindow *container); ContainerWindow *ContainerWindowCreate(); void ContainerWindowShow(ContainerWindow *, int32_t width, int32_t height); +void ShutdownModalCreate(); #include "settings.cpp" @@ -626,6 +627,8 @@ int ProcessGlobalKeyboardShortcuts(EsElement *, EsMessage *message) { ApplicationInstanceCreate(desktop.installedApplications[i]->id, nullptr, nullptr); } } + } else if (scancode == ES_SCANCODE_ACPI_POWER) { + ShutdownModalCreate(); } else { return 0; } @@ -2964,14 +2967,12 @@ void EmbeddedWindowDestroyed(EsObjectID id) { EsHeapFree(instance); } -void DesktopMessage(EsMessage *message) { +void DesktopSendMessage(EsMessage *message) { if (!desktop.clockReady) { desktop.clockReady = EsEventCreate(false); } - if (message->type == ES_MSG_POWER_BUTTON_PRESSED) { - ShutdownModalCreate(); - } else if (message->type == ES_MSG_EMBEDDED_WINDOW_DESTROYED) { + if (message->type == ES_MSG_EMBEDDED_WINDOW_DESTROYED) { EmbeddedWindowDestroyed(message->desktop.windowID); } else if (message->type == ES_MSG_DESKTOP) { uint8_t *buffer = (uint8_t *) EsHeapAllocate(message->desktop.bytes, false); @@ -3073,6 +3074,6 @@ void DesktopEntry() { while (true) { EsMessage *message = EsMessageReceive(); - DesktopMessage(message); + DesktopSendMessage(message); } } diff --git a/desktop/os.header b/desktop/os.header index a2bd3c6..bc31c74 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -966,7 +966,6 @@ enum EsMessageType { ES_MSG_SLIDER_MOVED = 0x3006 // The slider has been moved. // Desktop messages: - ES_MSG_POWER_BUTTON_PRESSED = 0x4801 ES_MSG_EMBEDDED_WINDOW_DESTROYED = 0x4802 ES_MSG_SET_SCREEN_RESOLUTION = 0x4803 ES_MSG_REGISTER_FILE_SYSTEM = 0x4804 diff --git a/drivers/acpica.cpp b/drivers/acpica.cpp index 1a3ef65..24dea2a 100644 --- a/drivers/acpica.cpp +++ b/drivers/acpica.cpp @@ -425,9 +425,8 @@ ES_EXTERN_C ACPI_STATUS AcpiOsEnterSleep(UINT8 sleepState, UINT32 registerAValue UINT32 ACPIPowerButtonPressed(void *) { KRegisterAsyncTask(&powerButtonAsyncTask, [] (KAsyncTask *) { - _EsMessageWithObject m = { nullptr, ES_MSG_POWER_BUTTON_PRESSED }; - if (scheduler.shutdown) return; - if (desktopProcess) desktopProcess->messageQueue.SendMessage(&m); + KKeyPress(ES_SCANCODE_ACPI_POWER | K_SCANCODE_KEY_PRESSED); + KKeyPress(ES_SCANCODE_ACPI_POWER | K_SCANCODE_KEY_RELEASED); }); return 0; diff --git a/kernel/cache.cpp b/kernel/cache.cpp index 0bfb35a..2f441ec 100644 --- a/kernel/cache.cpp +++ b/kernel/cache.cpp @@ -79,6 +79,8 @@ void CCSpaceUncover(CCSpace *cache, EsFileOffset removeStart, EsFileOffset remov EsError CCSpaceAccess(CCSpace *cache, K_USER_BUFFER void *buffer, EsFileOffset offset, EsFileOffset count, uint32_t flags, MMSpace *mapSpace = nullptr, unsigned mapFlags = ES_FLAGS_DEFAULT); +MMActiveSectionManager activeSectionManager; + #else CCCachedSection *CCFindCachedSectionContaining(CCSpace *cache, EsFileOffset sectionOffset) { diff --git a/kernel/drivers.cpp b/kernel/drivers.cpp index f463673..a808b9e 100644 --- a/kernel/drivers.cpp +++ b/kernel/drivers.cpp @@ -119,11 +119,11 @@ void DeviceRemovedRecurse(KDevice *device) { } if (device->flags & K_DEVICE_VISIBLE_TO_USER) { - EsMessage m; + _EsMessageWithObject m; EsMemoryZero(&m, sizeof(m)); - m.type = ES_MSG_DEVICE_DISCONNECTED; - m.device.id = device->objectID; - desktopProcess->messageQueue.SendMessage(nullptr, &m); + m.message.type = ES_MSG_DEVICE_DISCONNECTED; + m.message.device.id = device->objectID; + DesktopSendMessage(&m); } if (device->removed) { @@ -145,16 +145,16 @@ void KDeviceSendConnectedMessage(KDevice *device, EsDeviceType type) { KDeviceOpenHandle(device); - EsMessage m; + _EsMessageWithObject m; EsMemoryZero(&m, sizeof(m)); - m.type = ES_MSG_DEVICE_CONNECTED; - m.device.id = device->objectID; - m.device.type = type; - m.device.handle = desktopProcess->handleTable.OpenHandle(device, 0, KERNEL_OBJECT_DEVICE); + m.message.type = ES_MSG_DEVICE_CONNECTED; + m.message.device.id = device->objectID; + m.message.device.type = type; + m.message.device.handle = DesktopOpenHandle(device, 0, KERNEL_OBJECT_DEVICE); - if (m.device.handle) { - if (!desktopProcess->messageQueue.SendMessage(nullptr, &m)) { - desktopProcess->handleTable.CloseHandle(m.device.handle); // This will check that the handle is still valid. + if (m.message.device.handle) { + if (!DesktopSendMessage(&m)) { + DesktopCloseHandle(m.message.device.handle); // This will check that the handle is still valid. } } } diff --git a/kernel/files.cpp b/kernel/files.cpp index 628c5dc..5ee77b0 100644 --- a/kernel/files.cpp +++ b/kernel/files.cpp @@ -1876,11 +1876,11 @@ void FSRegisterBootFileSystem(KFileSystem *fileSystem, EsUniqueIdentifier identi void FSFileSystemDeviceRemoved(KDevice *device) { KFileSystem *fileSystem = (KFileSystem *) device; - EsMessage m; - EsMemoryZero(&m, sizeof(EsMessage)); - m.type = ES_MSG_UNREGISTER_FILE_SYSTEM; - m.unregisterFileSystem.id = fileSystem->objectID; - desktopProcess->messageQueue.SendMessage(nullptr, &m); + _EsMessageWithObject m; + EsMemoryZero(&m, sizeof(m)); + m.message.type = ES_MSG_UNREGISTER_FILE_SYSTEM; + m.message.unregisterFileSystem.id = fileSystem->objectID; + DesktopSendMessage(&m); } void FSRegisterFileSystem(KFileSystem *fileSystem) { @@ -1893,16 +1893,15 @@ void FSRegisterFileSystem(KFileSystem *fileSystem) { fileSystem->rootDirectory->directoryEntry->directoryChildren = fileSystem->rootDirectoryInitialChildren; FSNodeOpenHandle(fileSystem->rootDirectory, ES_FLAGS_DEFAULT, fileSystem->isBootFileSystem ? FS_NODE_OPEN_HANDLE_STANDARD : FS_NODE_OPEN_HANDLE_FIRST); - EsMessage m; - EsMemoryZero(&m, sizeof(EsMessage)); - m.type = ES_MSG_REGISTER_FILE_SYSTEM; - m.registerFileSystem.isBootFileSystem = fileSystem->isBootFileSystem; + _EsMessageWithObject m; + EsMemoryZero(&m, sizeof(m)); + m.message.type = ES_MSG_REGISTER_FILE_SYSTEM; + m.message.registerFileSystem.isBootFileSystem = fileSystem->isBootFileSystem; + m.message.registerFileSystem.rootDirectory = DesktopOpenHandle(fileSystem->rootDirectory, _ES_NODE_DIRECTORY_WRITE, KERNEL_OBJECT_NODE); - m.registerFileSystem.rootDirectory = desktopProcess->handleTable.OpenHandle(fileSystem->rootDirectory, _ES_NODE_DIRECTORY_WRITE, KERNEL_OBJECT_NODE); - - if (m.registerFileSystem.rootDirectory) { - if (!desktopProcess->messageQueue.SendMessage(nullptr, &m)) { - desktopProcess->handleTable.CloseHandle(m.registerFileSystem.rootDirectory); // This will check that the handle is still valid. + if (m.message.registerFileSystem.rootDirectory) { + if (!DesktopSendMessage(&m)) { + DesktopCloseHandle(m.message.registerFileSystem.rootDirectory); // This will check that the handle is still valid. } } diff --git a/kernel/graphics.cpp b/kernel/graphics.cpp index 63e41e5..bcac19c 100644 --- a/kernel/graphics.cpp +++ b/kernel/graphics.cpp @@ -113,10 +113,10 @@ void KRegisterGraphicsTarget(KGraphicsTarget *target) { #else windowManager.Initialise(); - EsMessage m; - EsMemoryZero(&m, sizeof(EsMessage)); - m.type = ES_MSG_SET_SCREEN_RESOLUTION; - desktopProcess->messageQueue.SendMessage(nullptr, &m); + _EsMessageWithObject m; + EsMemoryZero(&m, sizeof(m)); + m.message.type = ES_MSG_SET_SCREEN_RESOLUTION; + DesktopSendMessage(&m); #endif } diff --git a/kernel/memory.cpp b/kernel/memory.cpp index cf9d01b..96b9b73 100644 --- a/kernel/memory.cpp +++ b/kernel/memory.cpp @@ -302,7 +302,6 @@ void PMCopy(uintptr_t page, void *source, size_t pageCount); MMSpace _kernelMMSpace, _coreMMSpace; PMM pmm; -MMActiveSectionManager activeSectionManager; MMRegion *mmCoreRegions = (MMRegion *) MM_CORE_REGIONS_START; size_t mmCoreRegionCount, mmCoreRegionArrayCommit; diff --git a/kernel/objects.cpp b/kernel/objects.cpp index 0b076fb..3930f19 100644 --- a/kernel/objects.cpp +++ b/kernel/objects.cpp @@ -574,10 +574,6 @@ EsHandle MakeConstantBuffer(K_USER_BUFFER const void *data, size_t bytes, Proces return object ? process->handleTable.OpenHandle(object, 0, KERNEL_OBJECT_CONSTANT_BUFFER) : ES_INVALID_HANDLE; } -EsHandle MakeConstantBufferForDesktop(K_USER_BUFFER const void *data, size_t bytes) { - return MakeConstantBuffer(data, bytes, desktopProcess); -} - size_t Pipe::Access(void *_buffer, size_t bytes, bool write, bool user) { size_t amount = 0; Thread *currentThread = GetCurrentThread(); @@ -730,6 +726,12 @@ bool MessageQueue::SendMessage(_EsMessageWithObject *_message) { KEventSet(¬Empty, true); + // TODO Temporary. + static int largest = 0; + int size = messages.Length(); + if (size > largest) largest = size; + if (size > 40) KernelPanic("what\n"); + return true; } diff --git a/kernel/scheduler.cpp b/kernel/scheduler.cpp index 33c0911..54d3ca5 100644 --- a/kernel/scheduler.cpp +++ b/kernel/scheduler.cpp @@ -188,8 +188,6 @@ struct Process { }; struct Scheduler { - // External API: - void Yield(InterruptContext *context); void CreateProcessorThreads(CPULocalStorage *local); void AddActiveThread(Thread *thread, bool start /* put it at the start of the active list */); // Add an active thread into the queue. @@ -199,8 +197,6 @@ struct Scheduler { Thread *PickThread(CPULocalStorage *local); // Pick the next thread to execute. int8_t GetThreadEffectivePriority(Thread *thread); - // Variables: - KSpinlock dispatchSpinlock; // For accessing synchronisation objects, thread states, scheduling lists, etc. TODO Break this up! KSpinlock activeTimersSpinlock; // For accessing the activeTimers lists. LinkedList activeThreads[THREAD_PRIORITY_COUNT]; @@ -244,9 +240,14 @@ void ThreadSetTemporaryAddressSpace(MMSpace *space); Thread *ThreadSpawn(const char *cName, uintptr_t startAddress, uintptr_t argument1 = 0, uint32_t flags = ES_FLAGS_DEFAULT, Process *process = nullptr, uintptr_t argument2 = 0); +bool DesktopSendMessage(_EsMessageWithObject *message); +EsHandle DesktopOpenHandle(void *object, uint32_t flags, KernelObjectType type); +void DesktopCloseHandle(EsHandle handle); + Process _kernelProcess; Process *kernelProcess = &_kernelProcess; Process *desktopProcess; +KMutex desktopMutex; Scheduler scheduler; #endif @@ -544,7 +545,7 @@ void ProcessKill(Process *process) { EsMemoryZero(&m, sizeof(m)); m.message.type = ES_MSG_PROCESS_TERMINATED; m.message.crash.pid = process->id; - desktopProcess->messageQueue.SendMessage(&m); + DesktopSendMessage(&m); } } @@ -728,7 +729,7 @@ void ProcessLoadExecutable() { KLoadedExecutable application = {}; - if (thisProcess != desktopProcess && loadError == ES_SUCCESS) { + if (thisProcess->type != PROCESS_DESKTOP && loadError == ES_SUCCESS) { loadError = KLoadELF(thisProcess->executableNode, &application); } @@ -754,7 +755,7 @@ void ProcessLoadExecutable() { if (!startupInformation) { success = false; } else { - startupInformation->isDesktop = thisProcess == desktopProcess; + startupInformation->isDesktop = thisProcess->type == PROCESS_DESKTOP; startupInformation->isBundle = application.isBundle; startupInformation->applicationStartAddress = application.startAddress; startupInformation->tlsImageStart = application.tlsImageStart; @@ -1086,7 +1087,7 @@ void ProcessCrash(Process *process, EsCrashReason *crashReason) { m.message.type = ES_MSG_APPLICATION_CRASH; m.message.crash.pid = process->id; EsMemoryCopy(&m.message.crash.reason, crashReason, sizeof(EsCrashReason)); - desktopProcess->messageQueue.SendMessage(&m); + DesktopSendMessage(&m); } KMutexRelease(&process->crashMutex); @@ -1272,11 +1273,16 @@ void Scheduler::Yield(InterruptContext *context) { } void ProcessTerminateAll() { + KMutexAcquire(&desktopMutex); + scheduler.shutdown = true; // Close our handle to the desktop process. CloseHandleToObject(desktopProcess->executableMainThread, KERNEL_OBJECT_THREAD); CloseHandleToObject(desktopProcess, KERNEL_OBJECT_PROCESS); + desktopProcess = nullptr; + + KMutexRelease(&desktopMutex); KernelLog(LOG_INFO, "Scheduler", "terminating all processes", "ProcessTerminateAll - Terminating all processes....\n"); @@ -1331,6 +1337,31 @@ void KYield() { ProcessorFakeTimerInterrupt(); } +bool DesktopSendMessage(_EsMessageWithObject *message) { + bool result = false; + KMutexAcquire(&desktopMutex); + if (desktopProcess) result = desktopProcess->messageQueue.SendMessage(message); + KMutexRelease(&desktopMutex); + return result; +} + +EsHandle DesktopOpenHandle(void *object, uint32_t flags, KernelObjectType type) { + EsHandle result = ES_INVALID_HANDLE; + bool close = false; + KMutexAcquire(&desktopMutex); + if (desktopProcess) result = desktopProcess->handleTable.OpenHandle(object, flags, type); + else close = true; + KMutexRelease(&desktopMutex); + if (close) CloseHandleToObject(object, type, flags); + return result; +} + +void DesktopCloseHandle(EsHandle handle) { + KMutexAcquire(&desktopMutex); + if (desktopProcess) desktopProcess->handleTable.CloseHandle(handle); // This will check that the handle is still valid. + KMutexRelease(&desktopMutex); +} + uint64_t KCPUCurrentID() { return GetLocalStorage() ->processorID; } uint64_t KProcessCurrentID() { return GetCurrentThread()->process->id; } uint64_t KThreadCurrentID() { return GetCurrentThread() ->id; } diff --git a/kernel/synchronisation.cpp b/kernel/synchronisation.cpp index 594d02e..bbb9809 100644 --- a/kernel/synchronisation.cpp +++ b/kernel/synchronisation.cpp @@ -4,10 +4,6 @@ #ifdef IMPLEMENTATION -#ifdef DEBUG_BUILD -uintptr_t nextMutexID; -#endif - void KSpinlockAcquire(KSpinlock *spinlock) { if (scheduler.panic) return; @@ -187,6 +183,7 @@ bool KMutexAcquire(KMutex *mutex) { KMutexAssertLocked(mutex); if (!mutex->id) { + static uintptr_t nextMutexID; mutex->id = __sync_fetch_and_add(&nextMutexID, 1); } diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp index d21e059..9ca77c9 100644 --- a/kernel/syscall.cpp +++ b/kernel/syscall.cpp @@ -8,8 +8,6 @@ #ifdef IMPLEMENTATION -KMutex eventForwardMutex; - #define SYSCALL_BUFFER_LIMIT (64 * 1024 * 1024) // To prevent overflow and DOS attacks. #define SYSCALL_BUFFER(address, length, index, write) \ MMRegion *_region ## index = MMFindAndPinRegion(currentVMM, (address), (length)); \ @@ -1368,17 +1366,19 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_MESSAGE_DESKTOP) { OpenHandleToObject(pipe, KERNEL_OBJECT_PIPE, PIPE_WRITER); } + void *constantBuffer = MakeConstantBuffer(buffer, argument1); + _EsMessageWithObject m = {}; m.message.type = ES_MSG_DESKTOP; - m.message.desktop.buffer = MakeConstantBufferForDesktop(buffer, argument1); + m.message.desktop.buffer = constantBuffer ? DesktopOpenHandle(constantBuffer, ES_FLAGS_DEFAULT, KERNEL_OBJECT_CONSTANT_BUFFER) : ES_INVALID_HANDLE; m.message.desktop.bytes = argument1; m.message.desktop.windowID = window ? window->id : 0; m.message.desktop.processID = currentProcess->id; - m.message.desktop.pipe = pipe ? desktopProcess->handleTable.OpenHandle(pipe, PIPE_WRITER, KERNEL_OBJECT_PIPE) : ES_INVALID_HANDLE; + m.message.desktop.pipe = pipe ? DesktopOpenHandle(pipe, PIPE_WRITER, KERNEL_OBJECT_PIPE) : ES_INVALID_HANDLE; - if (!m.message.desktop.buffer || !desktopProcess->messageQueue.SendMessage(&m)) { - desktopProcess->handleTable.CloseHandle(m.message.desktop.buffer); - desktopProcess->handleTable.CloseHandle(m.message.desktop.pipe); + if (!m.message.desktop.buffer || !DesktopSendMessage(&m)) { + DesktopCloseHandle(m.message.desktop.buffer); + DesktopCloseHandle(m.message.desktop.pipe); } } diff --git a/kernel/windows.cpp b/kernel/windows.cpp index b167dd3..5a38dd1 100644 --- a/kernel/windows.cpp +++ b/kernel/windows.cpp @@ -399,12 +399,11 @@ void WindowManager::PressKey(uint32_t scancode) { KernelLog(LOG_VERBOSE, "WM", "press key", "WindowManager::PressKey - Received key press %x. Modifiers are %X. Keys held: %d/%d%z.\n", scancode, modifiers, keysHeld, maximumKeysHeld, message.keyboard.single ? " (single)" : ""); - if ((modifiers & ES_MODIFIER_CTRL) && (modifiers & ES_MODIFIER_FLAG)) { - desktopProcess->messageQueue.SendMessage(nullptr, &message); - } else if (activeWindow) { - SendMessageToWindow(activeWindow, &message); + if (((modifiers & ES_MODIFIER_CTRL) && (modifiers & ES_MODIFIER_FLAG)) || !activeWindow) { + _EsMessageWithObject messageWithObject = { nullptr, message }; + DesktopSendMessage(&messageWithObject); } else { - desktopProcess->messageQueue.SendMessage(nullptr, &message); + SendMessageToWindow(activeWindow, &message); } KMutexRelease(&mutex); @@ -928,17 +927,16 @@ void EmbeddedWindow::Destroy() { void EmbeddedWindow::Close() { KMutexAssertLocked(&windowManager.mutex); - EsMessage message; - EsMemoryZero(&message, sizeof(EsMessage)); - message.type = ES_MSG_WINDOW_DESTROYED; - owner->messageQueue.SendMessage(apiWindow, &message); + _EsMessageWithObject m; + EsMemoryZero(&m, sizeof(m)); + m.object = apiWindow; + m.message.type = ES_MSG_WINDOW_DESTROYED; + owner->messageQueue.SendMessage(&m); SetEmbedOwner(nullptr); - - if (!scheduler.shutdown) { - message.type = ES_MSG_EMBEDDED_WINDOW_DESTROYED; - message.desktop.windowID = id; - desktopProcess->messageQueue.SendMessage(nullptr, &message); - } + m.object = nullptr; + m.message.type = ES_MSG_EMBEDDED_WINDOW_DESTROYED; + m.message.desktop.windowID = id; + DesktopSendMessage(&m); if (container && container->embed == this) { container->SetEmbed(nullptr);