diff --git a/src_c/font.c b/src_c/font.c index 0505d77378..0270c41ea9 100644 --- a/src_c/font.c +++ b/src_c/font.c @@ -65,6 +65,7 @@ PyFont_New(TTF_Font *); #define PyFont_Check(x) ((x)->ob_type == &PyFont_Type) static int font_initialized = 0; +static unsigned int current_ttf_generation = 0; static const char font_defaultname[] = "freesansbold.ttf"; static const char pkgdatamodule_name[] = "pygame.pkgdata"; static const char resourcefunc_name[] = "getResource"; @@ -200,6 +201,7 @@ fontmodule_quit(PyObject *self) if (font_initialized) { TTF_Quit(); font_initialized = 0; + current_ttf_generation++; } Py_RETURN_NONE; } @@ -730,9 +732,16 @@ static void font_dealloc(PyFontObject *self) { TTF_Font *font = PyFont_AsFont(self); - - if (font && font_initialized) + if (font && font_initialized) { + if (self->ttf_init_generation != current_ttf_generation) { + // Since TTF_Font is a private structure + // it's impossible to access face field in a common way. + int** face_pp = font; + *face_pp = NULL; + } TTF_CloseFont(font); + self->font = NULL; + } if (self->weakreflist) PyObject_ClearWeakRefs((PyObject *)self); @@ -898,6 +907,7 @@ font_init(PyFontObject *self, PyObject *args, PyObject *kwds) Py_XDECREF(oencoded); Py_DECREF(obj); self->font = font; + self->ttf_init_generation = current_ttf_generation; return 0; error: diff --git a/src_c/include/pygame_font.h b/src_c/include/pygame_font.h index 3fe4500a13..00160c823d 100644 --- a/src_c/include/pygame_font.h +++ b/src_c/include/pygame_font.h @@ -29,6 +29,7 @@ typedef struct { PyObject_HEAD TTF_Font* font; PyObject* weakreflist; + unsigned int ttf_init_generation; } PyFontObject; #define PyFont_AsFont(x) (((PyFontObject*)x)->font) diff --git a/test/font_test.py b/test/font_test.py index 91d096a940..773a4d536e 100644 --- a/test/font_test.py +++ b/test/font_test.py @@ -206,6 +206,16 @@ def test_issue_font_alphablit(self): self.assertEqual(pre_blit_corner_pixel, post_blit_corner_pixel) + def test_segfault_after_reinit(self): + """ Reinitialization of font module should not cause + segmentation fault """ + import gc + font = pygame_font.Font(None, 20) + pygame_font.quit() + pygame_font.init() + del font + gc.collect() + def test_quit(self): pygame_font.quit()