-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Don't execute the proxy queue while adding to it from same thread. #24565
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fdf56ef
f9af064
1b13750
f192ce3
6dde91f
f6868ef
24a7490
27de752
97fb5fd
dcfd188
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
19540 | ||
19590 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
19541 | ||
19591 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Copyright 2025 The Emscripten Authors. All rights reserved. | ||
// Emscripten is available under two separate licenses, the MIT license and the | ||
// University of Illinois/NCSA Open Source License. Both these licenses can be | ||
// found in the LICENSE file. | ||
|
||
#include <pthread.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
#include <emscripten/console.h> | ||
#include <emscripten/heap.h> | ||
#include <emscripten/proxying.h> | ||
#include <emscripten/threading.h> | ||
|
||
// In the actual implementation of malloc the system queue may be executed | ||
// non-deterministically if malloc is waiting on a mutex. This wraps malloc and | ||
// executes the system queue during every allocation to make the behavior | ||
// deterministic. | ||
void *malloc(size_t size) { | ||
if (emscripten_is_main_runtime_thread()) { | ||
emscripten_proxy_execute_queue(emscripten_proxy_get_system_queue()); | ||
} | ||
void *ptr = emscripten_builtin_malloc(size); | ||
return ptr; | ||
} | ||
|
||
void task(void* arg) { | ||
emscripten_out("task\n"); | ||
} | ||
|
||
int main() { | ||
// Tests for a deadlock scenario that can occur when sending a task. | ||
// The sequence of events is: | ||
// 1. Sending a task locks the queue. | ||
// 2. Allocating a new task queue calls malloc. | ||
// 3. Malloc then attempts to execute and lock the already-locked queue, | ||
// causing a deadlock. | ||
// This test ensures our implementation prevents this re-entrant lock. | ||
emscripten_proxy_async(emscripten_proxy_get_system_queue(), pthread_self(), task, NULL); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh nice, so you don't even need a second thread! Makes sense I guess since this is a double-lock/self-deadlock issue. Is it valid to send work to yourself? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. test_pthread_proxying.c has a test for proxing to itself, so I assume so. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, but only asynchronous self-proxying is allowed, since synchronous self-proxying would obviously deadlock. |
||
emscripten_out("done\n"); | ||
} |
Uh oh!
There was an error while loading. Please reload this page.