fix race on desktopProcess in shut down

This commit is contained in:
nakst 2021-11-13 19:33:44 +00:00
parent 2436959c84
commit c2dc5adbe7
14 changed files with 106 additions and 79 deletions

View File

@ -1483,7 +1483,7 @@ extern "C" void _start(EsProcessStartupInformation *_startupInformation) {
while (!api.foundBootFileSystem) {
EsMessage *message = EsMessageReceive();
DesktopMessage(message);
DesktopSendMessage(message);
}
size_t fileSize;

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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.
}
}
}

View File

@ -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.
}
}

View File

@ -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
}

View File

@ -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;

View File

@ -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(&notEmpty, true);
// TODO Temporary.
static int largest = 0;
int size = messages.Length();
if (size > largest) largest = size;
if (size > 40) KernelPanic("what\n");
return true;
}

View File

@ -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<Thread> 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; }

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);