summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2017-02-23 18:15:05 +0200
committerEli Zaretskii <eliz@gnu.org>2017-02-23 18:15:05 +0200
commit5114b3a2047a9bcdb72fddf35e70201c16eb39a3 (patch)
treeee886ff5771ec6ae69c15a317f19741be31a7fab
parent4381015bd13c51cd47aad34bed82f40485d774d3 (diff)
downloademacs-5114b3a2047a9bcdb72fddf35e70201c16eb39a3.tar.gz
Avoid quitting inside a critical section on MS-Windows
* src/w32uniscribe.c (uniscribe_list_family): * src/w32font.c (w32font_list_family, w32font_text_extents) (w32font_list_internal, w32font_match_internal) (list_all_matching_fonts): Prevent quitting while these functions cons lists of fonts, to avoid leaving the critical section taken by the main thread, which will then cause any other thread attempting to enter the critical section to hang. (Bug#25279)
-rw-r--r--src/w32font.c44
-rw-r--r--src/w32uniscribe.c7
2 files changed, 51 insertions, 0 deletions
diff --git a/src/w32font.c b/src/w32font.c
index eff1a78937a..37df1bc43c0 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -285,18 +285,25 @@ static Lisp_Object
w32font_list_family (struct frame *f)
{
Lisp_Object list = Qnil;
+ Lisp_Object prev_quit = Vinhibit_quit;
LOGFONT font_match_pattern;
HDC dc;
memset (&font_match_pattern, 0, sizeof (font_match_pattern));
font_match_pattern.lfCharSet = DEFAULT_CHARSET;
+ /* Prevent quitting while EnumFontFamiliesEx runs and conses the
+ list it will return. That's because get_frame_dc acquires the
+ critical section, so we cannot quit before we release it in
+ release_frame_dc. */
+ Vinhibit_quit = Qt;
dc = get_frame_dc (f);
EnumFontFamiliesEx (dc, &font_match_pattern,
(FONTENUMPROC) add_font_name_to_list,
(LPARAM) &list, 0);
release_frame_dc (f, dc);
+ Vinhibit_quit = prev_quit;
return list;
}
@@ -434,6 +441,7 @@ w32font_text_extents (struct font *font, unsigned *code,
WORD *wcode;
SIZE size;
bool first;
+ Lisp_Object prev_quit = Vinhibit_quit;
struct w32font_info *w32_font = (struct w32font_info *) font;
@@ -480,6 +488,12 @@ w32font_text_extents (struct font *font, unsigned *code,
is updated to pass in a frame. */
f = XFRAME (selected_frame);
+ /* Prevent quitting while EnumFontFamiliesEx runs and
+ conses the list it will return. That's because
+ get_frame_dc acquires the critical section, so we
+ cannot quit before we release it in release_frame_dc. */
+ prev_quit = Vinhibit_quit;
+ Vinhibit_quit = Qt;
dc = get_frame_dc (f);
old_font = SelectObject (dc, w32_font->hfont);
}
@@ -520,6 +534,7 @@ w32font_text_extents (struct font *font, unsigned *code,
/* Restore state and release DC. */
SelectObject (dc, old_font);
release_frame_dc (f, dc);
+ Vinhibit_quit = prev_quit;
}
return;
}
@@ -556,6 +571,12 @@ w32font_text_extents (struct font *font, unsigned *code,
frame. */
f = XFRAME (selected_frame);
+ /* Prevent quitting while EnumFontFamiliesEx runs and conses the
+ list it will return. That's because get_frame_dc acquires
+ the critical section, so we cannot quit before we release it
+ in release_frame_dc. */
+ prev_quit = Vinhibit_quit;
+ Vinhibit_quit = Qt;
dc = get_frame_dc (f);
old_font = SelectObject (dc, w32_font->hfont);
}
@@ -586,6 +607,7 @@ w32font_text_extents (struct font *font, unsigned *code,
/* Restore state and release DC. */
SelectObject (dc, old_font);
release_frame_dc (f, dc);
+ Vinhibit_quit = prev_quit;
}
/* w32 implementation of draw for font backend.
@@ -812,12 +834,20 @@ w32font_list_internal (struct frame *f, Lisp_Object font_spec,
}
else
{
+ Lisp_Object prev_quit = Vinhibit_quit;
+
+ /* Prevent quitting while EnumFontFamiliesEx runs and conses the
+ list it will return. That's because get_frame_dc acquires
+ the critical section, so we cannot quit before we release it
+ in release_frame_dc. */
+ Vinhibit_quit = Qt;
dc = get_frame_dc (f);
EnumFontFamiliesEx (dc, &match_data.pattern,
(FONTENUMPROC) add_font_entity_to_list,
(LPARAM) &match_data, 0);
release_frame_dc (f, dc);
+ Vinhibit_quit = prev_quit;
}
return match_data.list;
@@ -844,12 +874,19 @@ w32font_match_internal (struct frame *f, Lisp_Object font_spec,
if (opentype_only)
match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
+ /* Prevent quitting while EnumFontFamiliesEx runs and conses the
+ list it will return. That's because get_frame_dc acquires the
+ critical section, so we cannot quit before we release it in
+ release_frame_dc. */
+ Lisp_Object prev_quit = Vinhibit_quit;
+ Vinhibit_quit = Qt;
dc = get_frame_dc (f);
EnumFontFamiliesEx (dc, &match_data.pattern,
(FONTENUMPROC) add_one_font_entity_to_list,
(LPARAM) &match_data, 0);
release_frame_dc (f, dc);
+ Vinhibit_quit = prev_quit;
return NILP (match_data.list) ? Qnil : XCAR (match_data.list);
}
@@ -2064,6 +2101,12 @@ list_all_matching_fonts (struct font_callback_data *match_data)
Lisp_Object families = w32font_list_family (XFRAME (match_data->frame));
struct frame *f = XFRAME (match_data->frame);
+ /* Prevent quitting while EnumFontFamiliesEx runs and conses the
+ list it will return. That's because get_frame_dc acquires the
+ critical section, so we cannot quit before we release it in
+ release_frame_dc. */
+ Lisp_Object prev_quit = Vinhibit_quit;
+ Vinhibit_quit = Qt;
dc = get_frame_dc (f);
while (!NILP (families))
@@ -2091,6 +2134,7 @@ list_all_matching_fonts (struct font_callback_data *match_data)
}
release_frame_dc (f, dc);
+ Vinhibit_quit = prev_quit;
}
static Lisp_Object
diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c
index 1584d80f203..e4055638cc4 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -89,12 +89,19 @@ uniscribe_list_family (struct frame *f)
/* Limit enumerated fonts to outline fonts to save time. */
font_match_pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
+ /* Prevent quitting while EnumFontFamiliesEx runs and conses the
+ list it will return. That's because get_frame_dc acquires the
+ critical section, so we cannot quit before we release it in
+ release_frame_dc. */
+ Lisp_Object prev_quit = Vinhibit_quit;
+ Vinhibit_quit = Qt;
dc = get_frame_dc (f);
EnumFontFamiliesEx (dc, &font_match_pattern,
(FONTENUMPROC) add_opentype_font_name_to_list,
(LPARAM) &list, 0);
release_frame_dc (f, dc);
+ Vinhibit_quit = prev_quit;
return list;
}