diff --git a/changelogs/unreleased/gh-10278-vy-tuple-format-lookup-fix.md b/changelogs/unreleased/gh-10278-vy-tuple-format-lookup-fix.md new file mode 100644 index 0000000000000000000000000000000000000000..fd2a6322f895ee5682001a28ad26e6e6724675a2 --- /dev/null +++ b/changelogs/unreleased/gh-10278-vy-tuple-format-lookup-fix.md @@ -0,0 +1,4 @@ +## bugfix/vinyl + +* Fixed a multi-threading race condition that could cause a writer thread to + crash while looking up a tuple format (gh-10278). diff --git a/src/box/tuple_format.c b/src/box/tuple_format.c index 54d6ededac260a914d8df3bd2686f2cacb38264a..36dbdf96ad0aa61341485254c8753c911fb7d44a 100644 --- a/src/box/tuple_format.c +++ b/src/box/tuple_format.c @@ -44,10 +44,10 @@ #include <PMurHash.h> /** Global table of tuple formats */ -struct tuple_format **tuple_formats; +struct tuple_format *tuple_formats[FORMAT_ID_MAX + 1]; static intptr_t recycled_format_ids = FORMAT_ID_NIL; -static uint32_t formats_size = 0, formats_capacity = 0; +static uint32_t formats_size = 0; static uint64_t formats_epoch = 0; /** @@ -660,27 +660,9 @@ static int tuple_format_register(struct tuple_format *format) { if (recycled_format_ids != FORMAT_ID_NIL) { - format->id = (uint16_t) recycled_format_ids; recycled_format_ids = (intptr_t) tuple_formats[recycled_format_ids]; } else { - if (formats_size == formats_capacity) { - uint32_t new_capacity = formats_capacity ? - formats_capacity * 2 : 16; - struct tuple_format **formats; - formats = (struct tuple_format **) - realloc(tuple_formats, new_capacity * - sizeof(tuple_formats[0])); - if (formats == NULL) { - diag_set(OutOfMemory, - sizeof(struct tuple_format), "malloc", - "tuple_formats"); - return -1; - } - - formats_capacity = new_capacity; - tuple_formats = formats; - } uint32_t formats_size_max = FORMAT_ID_MAX + 1; struct errinj *inj = errinj(ERRINJ_TUPLE_FORMAT_COUNT, ERRINJ_INT); @@ -688,7 +670,7 @@ tuple_format_register(struct tuple_format *format) formats_size_max = inj->iparam; if (formats_size >= formats_size_max) { diag_set(ClientError, ER_TUPLE_FORMAT_LIMIT, - (unsigned) formats_capacity); + (unsigned)formats_size_max); return -1; } format->id = formats_size++; @@ -1290,10 +1272,8 @@ void tuple_format_init() { tuple_formats_hash = mh_tuple_format_new(); - tuple_formats = NULL; recycled_format_ids = FORMAT_ID_NIL; formats_size = 0; - formats_capacity = 0; } /** Destroy tuple format subsystem and free resourses */ @@ -1314,7 +1294,6 @@ tuple_format_free() free(*format); } } - free(tuple_formats); mh_tuple_format_delete(tuple_formats_hash); } diff --git a/src/box/tuple_format.h b/src/box/tuple_format.h index 81eaa4f77a4815efc6b4fb3d626b046c8345d412..b006dc3d60a86e00d5ba01c6823909f027fdae12 100644 --- a/src/box/tuple_format.h +++ b/src/box/tuple_format.h @@ -373,7 +373,7 @@ tuple_format_field(struct tuple_format *format, uint32_t fieldno) return tuple_format_field_by_path(format, fieldno, NULL, 0, 0); } -extern struct tuple_format **tuple_formats; +extern struct tuple_format *tuple_formats[]; static inline uint32_t tuple_format_id(struct tuple_format *format) diff --git a/test/wal_off/alter.result b/test/wal_off/alter.result index 042ca67bcadbae65390741866a28406a253b9e1e..c0aff9502f7f6363a01d890e7b50d1bb07d5cf2f 100644 --- a/test/wal_off/alter.result +++ b/test/wal_off/alter.result @@ -24,7 +24,7 @@ for k = 1, box.schema.FORMAT_ID_MAX, 1 do table.insert(spaces, s) end; --- -- error: 'Tuple format limit reached: 65536' +- error: 'Tuple format limit reached: 65535' ... #spaces > 65000; ---