-
-
Notifications
You must be signed in to change notification settings - Fork 34.5k
bpo-33015: Add a wrapper for thread function in PyThread_start_new_thread #6008
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 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
PyThread_start_new_thread accepts a function of type void (*) (void *), which does not match with the pthread_create function callback prototype void *(*) (void *). This is undefined behaviour and hence results in an invalid function cast warning with gcc8. Fix this by wrapping the function in an internal pthread function callback that returns NULL.
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| Add a wrapper for the thread function argument in | ||
| `PyThread_start_new_thread` to avoid an incompatible cast warning with gcc | ||
| 8. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -152,6 +152,31 @@ PyThread__init_thread(void) | |
| * Thread support. | ||
| */ | ||
|
|
||
| /* The thread function argument passed to PyThread_start_new_thread has a | ||
| * different type compared to the thread function passed to the POSIX | ||
| * pthread_create function and the result of forcibly casting it to the latter | ||
| * type is undefined. The pythread_fn struct and the pythread_helper_fn below | ||
| * help work around this in a conforming manner by wrapping around the thread | ||
| * function. | ||
| */ | ||
| typedef struct { | ||
| void (*func) (void *); | ||
| void *arg; | ||
| } pythread_fn; | ||
|
Member
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 suggest to rename it to pythread_callback since it's not only a function but function+arguments (or maybe pythread_func). |
||
|
|
||
| static void * | ||
| pythread_helper_fn(void *fn) | ||
|
Member
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. nitpick: i suggest to rename it to "pythread_wrapper". To me, it's more a wrapper than an helper ;-) |
||
| { | ||
| pythread_fn *pfn = fn; | ||
|
|
||
| void (*func)(void *) = pfn->func; | ||
| void *arg = pfn->arg; | ||
|
|
||
|
Member
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. nitpick: please move this empty line after the free, not before :-) to make it clear that the memory is freed when the function is called. |
||
| PyMem_RawFree((void *)fn); | ||
| func(arg); | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| unsigned long | ||
| PyThread_start_new_thread(void (*func)(void *), void *arg) | ||
|
|
@@ -188,21 +213,32 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) | |
| pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM); | ||
| #endif | ||
|
|
||
| pythread_fn *fn = (pythread_fn *)PyMem_RawMalloc(sizeof (pythread_fn)); | ||
|
Member
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 cast is useless, no? |
||
|
|
||
| if (fn == NULL) | ||
| return PYTHREAD_INVALID_THREAD_ID; | ||
|
vstinner marked this conversation as resolved.
Outdated
|
||
|
|
||
| fn->func = func; | ||
| fn->arg = arg; | ||
|
|
||
| status = pthread_create(&th, | ||
| #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) | ||
| &attrs, | ||
| #else | ||
| (pthread_attr_t*)NULL, | ||
| #endif | ||
| (void* (*)(void *))func, | ||
| (void *)arg | ||
| pythread_helper_fn, | ||
| fn | ||
| ); | ||
|
|
||
| #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) | ||
| pthread_attr_destroy(&attrs); | ||
| #endif | ||
| if (status != 0) | ||
|
|
||
| if (status != 0) { | ||
| PyMem_RawFree((void *)fn); | ||
|
Member
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 cast is useless, no? |
||
| return PYTHREAD_INVALID_THREAD_ID; | ||
| } | ||
|
|
||
| pthread_detach(th); | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.