Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add a wrapper for thread function in PyThread_start_new_thread
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
siddhesh authored and vstinner committed Nov 30, 2018
commit d3a972434c8aec0a47500d7b368130701b4f0a52
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.
42 changes: 39 additions & 3 deletions Python/thread_pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Comment thread
siddhesh marked this conversation as resolved.
Outdated
void (*func) (void *);
void *arg;
} pythread_fn;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The 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)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The 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)
Expand Down Expand Up @@ -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));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The 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;
Comment thread
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);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Expand Down