-
Notifications
You must be signed in to change notification settings - Fork 202
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
Fix a use-after-free bug for detached threads #420
Changes from 1 commit
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 |
---|---|---|
|
@@ -60,6 +60,18 @@ void __tl_sync(pthread_t td) | |
if (tl_lock_waiters) __wake(&__thread_list_lock, 1, 0); | ||
} | ||
|
||
#ifndef __wasilibc_unmodified_upstream | ||
/* this queue has at most one entry */ | ||
static void *map_base_lazy_free_queue; | ||
|
||
static void process_map_base_lazy_free_queue() | ||
{ | ||
/* called with __tl_lock held */ | ||
free(map_base_lazy_free_queue); | ||
map_base_lazy_free_queue = NULL; | ||
} | ||
#endif | ||
|
||
#ifdef __wasilibc_unmodified_upstream | ||
_Noreturn void __pthread_exit(void *result) | ||
#else | ||
|
@@ -182,7 +194,17 @@ static void __pthread_exit(void *result) | |
} | ||
#else | ||
if (state==DT_DETACHED && self->map_base) { | ||
free(self->map_base); | ||
// As we use malloc/free which is considerably more complex | ||
// than mmap/munmap to call and can even require a valid | ||
// thread context, it's difficult to implement __unmapself. | ||
// | ||
// Here we take an alternative approach which simply defers | ||
// the deallocation. An obvious downside of this approach is | ||
// that it keeps the stack longer. (possibly forever.) | ||
// To avoid wasting too much memory, we keep the free queue | ||
// length at most one. | ||
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. Can we be consistent about C vs C++ comments? Below you've used C multi-line comment. 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. i followed nearby code. 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. fixed |
||
process_map_base_lazy_free_queue(); | ||
map_base_lazy_free_queue = self->map_base; | ||
// Can't use `exit()` here, because it is too high level | ||
return; | ||
} | ||
|
@@ -424,6 +446,16 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att | |
if (map == MAP_FAILED) goto fail; | ||
} | ||
#else | ||
/* | ||
* Process the free queue before allocationg a new one. | ||
* Hopefully it enables a reuse of the memory. | ||
* | ||
* Note: We can't perform a simple "handoff" becasue allocation | ||
* sizes might be different. (eg. the stack size might differ) | ||
*/ | ||
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. The comment style within this file seems to be:
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. fixed |
||
__tl_lock(); | ||
process_map_base_lazy_free_queue(); | ||
__tl_unlock(); | ||
map = malloc(size); | ||
if (!map) goto fail; | ||
#endif | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Give that, I'm not sure
queue
is the right name for this.I'm not sure I have any better suggestions though. Maybe
deferred_deallocation
andprocess_deferred_deallocation
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed