diff options
author | Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> | 2022-08-16 18:22:14 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-16 18:22:14 (GMT) |
commit | 9b30b965f0c1da216397b495faef4d93ff7a5328 (patch) | |
tree | 1d59dfece82c7638a9516987f492200ce3480e37 /Python/getargs.c | |
parent | 48174fa0b949d6b1d0c1f074e7d4e47793759a43 (diff) | |
download | cpython-9b30b965f0c1da216397b495faef4d93ff7a5328.zip cpython-9b30b965f0c1da216397b495faef4d93ff7a5328.tar.gz cpython-9b30b965f0c1da216397b495faef4d93ff7a5328.tar.bz2 |
GH-95909: Make `_PyArg_Parser` initialization thread safe (GH-95958)
Diffstat (limited to 'Python/getargs.c')
-rw-r--r-- | Python/getargs.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/Python/getargs.c b/Python/getargs.c index 457dd99..f0b84b8 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1974,15 +1974,10 @@ new_kwtuple(const char * const *keywords, int total, int pos) } static int -parser_init(struct _PyArg_Parser *parser) +_parser_init(struct _PyArg_Parser *parser) { const char * const *keywords = parser->keywords; assert(keywords != NULL); - - if (parser->initialized) { - assert(parser->kwtuple != NULL); - return 1; - } assert(parser->pos == 0 && (parser->format == NULL || parser->fname == NULL) && parser->custom_msg == NULL && @@ -2035,6 +2030,28 @@ parser_init(struct _PyArg_Parser *parser) return 1; } +static int +parser_init(struct _PyArg_Parser *parser) +{ + // volatile as it can be modified by other threads + // and should not be optimized or reordered by compiler + if (*((volatile int *)&parser->initialized)) { + assert(parser->kwtuple != NULL); + return 1; + } + PyThread_acquire_lock(_PyRuntime.getargs.mutex, WAIT_LOCK); + // Check again if another thread initialized the parser + // while we were waiting for the lock. + if (*((volatile int *)&parser->initialized)) { + assert(parser->kwtuple != NULL); + PyThread_release_lock(_PyRuntime.getargs.mutex); + return 1; + } + int ret = _parser_init(parser); + PyThread_release_lock(_PyRuntime.getargs.mutex); + return ret; +} + static void parser_clear(struct _PyArg_Parser *parser) { |