diff options
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 457dd99ce4a..f0b84b8338d 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) { |