summaryrefslogtreecommitdiffstats
path: root/Python/getargs.c
diff options
context:
space:
mode:
authorKumar Aditya <59607654+kumaraditya303@users.noreply.github.com>2022-08-16 18:22:14 (GMT)
committerGitHub <noreply@github.com>2022-08-16 18:22:14 (GMT)
commit9b30b965f0c1da216397b495faef4d93ff7a5328 (patch)
tree1d59dfece82c7638a9516987f492200ce3480e37 /Python/getargs.c
parent48174fa0b949d6b1d0c1f074e7d4e47793759a43 (diff)
downloadcpython-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.c29
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)
{