aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2017-02-23 18:15:05 +0200
committerEli Zaretskii2017-02-23 18:15:05 +0200
commit5114b3a2047a9bcdb72fddf35e70201c16eb39a3 (patch)
treeee886ff5771ec6ae69c15a317f19741be31a7fab
parent4381015bd13c51cd47aad34bed82f40485d774d3 (diff)
downloademacs-5114b3a2047a9bcdb72fddf35e70201c16eb39a3.tar.gz
emacs-5114b3a2047a9bcdb72fddf35e70201c16eb39a3.zip
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
285w32font_list_family (struct frame *f) 285w32font_list_family (struct frame *f)
286{ 286{
287 Lisp_Object list = Qnil; 287 Lisp_Object list = Qnil;
288 Lisp_Object prev_quit = Vinhibit_quit;
288 LOGFONT font_match_pattern; 289 LOGFONT font_match_pattern;
289 HDC dc; 290 HDC dc;
290 291
291 memset (&font_match_pattern, 0, sizeof (font_match_pattern)); 292 memset (&font_match_pattern, 0, sizeof (font_match_pattern));
292 font_match_pattern.lfCharSet = DEFAULT_CHARSET; 293 font_match_pattern.lfCharSet = DEFAULT_CHARSET;
293 294
295 /* Prevent quitting while EnumFontFamiliesEx runs and conses the
296 list it will return. That's because get_frame_dc acquires the
297 critical section, so we cannot quit before we release it in
298 release_frame_dc. */
299 Vinhibit_quit = Qt;
294 dc = get_frame_dc (f); 300 dc = get_frame_dc (f);
295 301
296 EnumFontFamiliesEx (dc, &font_match_pattern, 302 EnumFontFamiliesEx (dc, &font_match_pattern,
297 (FONTENUMPROC) add_font_name_to_list, 303 (FONTENUMPROC) add_font_name_to_list,
298 (LPARAM) &list, 0); 304 (LPARAM) &list, 0);
299 release_frame_dc (f, dc); 305 release_frame_dc (f, dc);
306 Vinhibit_quit = prev_quit;
300 307
301 return list; 308 return list;
302} 309}
@@ -434,6 +441,7 @@ w32font_text_extents (struct font *font, unsigned *code,
434 WORD *wcode; 441 WORD *wcode;
435 SIZE size; 442 SIZE size;
436 bool first; 443 bool first;
444 Lisp_Object prev_quit = Vinhibit_quit;
437 445
438 struct w32font_info *w32_font = (struct w32font_info *) font; 446 struct w32font_info *w32_font = (struct w32font_info *) font;
439 447
@@ -480,6 +488,12 @@ w32font_text_extents (struct font *font, unsigned *code,
480 is updated to pass in a frame. */ 488 is updated to pass in a frame. */
481 f = XFRAME (selected_frame); 489 f = XFRAME (selected_frame);
482 490
491 /* Prevent quitting while EnumFontFamiliesEx runs and
492 conses the list it will return. That's because
493 get_frame_dc acquires the critical section, so we
494 cannot quit before we release it in release_frame_dc. */
495 prev_quit = Vinhibit_quit;
496 Vinhibit_quit = Qt;
483 dc = get_frame_dc (f); 497 dc = get_frame_dc (f);
484 old_font = SelectObject (dc, w32_font->hfont); 498 old_font = SelectObject (dc, w32_font->hfont);
485 } 499 }
@@ -520,6 +534,7 @@ w32font_text_extents (struct font *font, unsigned *code,
520 /* Restore state and release DC. */ 534 /* Restore state and release DC. */
521 SelectObject (dc, old_font); 535 SelectObject (dc, old_font);
522 release_frame_dc (f, dc); 536 release_frame_dc (f, dc);
537 Vinhibit_quit = prev_quit;
523 } 538 }
524 return; 539 return;
525 } 540 }
@@ -556,6 +571,12 @@ w32font_text_extents (struct font *font, unsigned *code,
556 frame. */ 571 frame. */
557 f = XFRAME (selected_frame); 572 f = XFRAME (selected_frame);
558 573
574 /* Prevent quitting while EnumFontFamiliesEx runs and conses the
575 list it will return. That's because get_frame_dc acquires
576 the critical section, so we cannot quit before we release it
577 in release_frame_dc. */
578 prev_quit = Vinhibit_quit;
579 Vinhibit_quit = Qt;
559 dc = get_frame_dc (f); 580 dc = get_frame_dc (f);
560 old_font = SelectObject (dc, w32_font->hfont); 581 old_font = SelectObject (dc, w32_font->hfont);
561 } 582 }
@@ -586,6 +607,7 @@ w32font_text_extents (struct font *font, unsigned *code,
586 /* Restore state and release DC. */ 607 /* Restore state and release DC. */
587 SelectObject (dc, old_font); 608 SelectObject (dc, old_font);
588 release_frame_dc (f, dc); 609 release_frame_dc (f, dc);
610 Vinhibit_quit = prev_quit;
589} 611}
590 612
591/* w32 implementation of draw for font backend. 613/* w32 implementation of draw for font backend.
@@ -812,12 +834,20 @@ w32font_list_internal (struct frame *f, Lisp_Object font_spec,
812 } 834 }
813 else 835 else
814 { 836 {
837 Lisp_Object prev_quit = Vinhibit_quit;
838
839 /* Prevent quitting while EnumFontFamiliesEx runs and conses the
840 list it will return. That's because get_frame_dc acquires
841 the critical section, so we cannot quit before we release it
842 in release_frame_dc. */
843 Vinhibit_quit = Qt;
815 dc = get_frame_dc (f); 844 dc = get_frame_dc (f);
816 845
817 EnumFontFamiliesEx (dc, &match_data.pattern, 846 EnumFontFamiliesEx (dc, &match_data.pattern,
818 (FONTENUMPROC) add_font_entity_to_list, 847 (FONTENUMPROC) add_font_entity_to_list,
819 (LPARAM) &match_data, 0); 848 (LPARAM) &match_data, 0);
820 release_frame_dc (f, dc); 849 release_frame_dc (f, dc);
850 Vinhibit_quit = prev_quit;
821 } 851 }
822 852
823 return match_data.list; 853 return match_data.list;
@@ -844,12 +874,19 @@ w32font_match_internal (struct frame *f, Lisp_Object font_spec,
844 if (opentype_only) 874 if (opentype_only)
845 match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS; 875 match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
846 876
877 /* Prevent quitting while EnumFontFamiliesEx runs and conses the
878 list it will return. That's because get_frame_dc acquires the
879 critical section, so we cannot quit before we release it in
880 release_frame_dc. */
881 Lisp_Object prev_quit = Vinhibit_quit;
882 Vinhibit_quit = Qt;
847 dc = get_frame_dc (f); 883 dc = get_frame_dc (f);
848 884
849 EnumFontFamiliesEx (dc, &match_data.pattern, 885 EnumFontFamiliesEx (dc, &match_data.pattern,
850 (FONTENUMPROC) add_one_font_entity_to_list, 886 (FONTENUMPROC) add_one_font_entity_to_list,
851 (LPARAM) &match_data, 0); 887 (LPARAM) &match_data, 0);
852 release_frame_dc (f, dc); 888 release_frame_dc (f, dc);
889 Vinhibit_quit = prev_quit;
853 890
854 return NILP (match_data.list) ? Qnil : XCAR (match_data.list); 891 return NILP (match_data.list) ? Qnil : XCAR (match_data.list);
855} 892}
@@ -2064,6 +2101,12 @@ list_all_matching_fonts (struct font_callback_data *match_data)
2064 Lisp_Object families = w32font_list_family (XFRAME (match_data->frame)); 2101 Lisp_Object families = w32font_list_family (XFRAME (match_data->frame));
2065 struct frame *f = XFRAME (match_data->frame); 2102 struct frame *f = XFRAME (match_data->frame);
2066 2103
2104 /* Prevent quitting while EnumFontFamiliesEx runs and conses the
2105 list it will return. That's because get_frame_dc acquires the
2106 critical section, so we cannot quit before we release it in
2107 release_frame_dc. */
2108 Lisp_Object prev_quit = Vinhibit_quit;
2109 Vinhibit_quit = Qt;
2067 dc = get_frame_dc (f); 2110 dc = get_frame_dc (f);
2068 2111
2069 while (!NILP (families)) 2112 while (!NILP (families))
@@ -2091,6 +2134,7 @@ list_all_matching_fonts (struct font_callback_data *match_data)
2091 } 2134 }
2092 2135
2093 release_frame_dc (f, dc); 2136 release_frame_dc (f, dc);
2137 Vinhibit_quit = prev_quit;
2094} 2138}
2095 2139
2096static Lisp_Object 2140static 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)
89 /* Limit enumerated fonts to outline fonts to save time. */ 89 /* Limit enumerated fonts to outline fonts to save time. */
90 font_match_pattern.lfOutPrecision = OUT_OUTLINE_PRECIS; 90 font_match_pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
91 91
92 /* Prevent quitting while EnumFontFamiliesEx runs and conses the
93 list it will return. That's because get_frame_dc acquires the
94 critical section, so we cannot quit before we release it in
95 release_frame_dc. */
96 Lisp_Object prev_quit = Vinhibit_quit;
97 Vinhibit_quit = Qt;
92 dc = get_frame_dc (f); 98 dc = get_frame_dc (f);
93 99
94 EnumFontFamiliesEx (dc, &font_match_pattern, 100 EnumFontFamiliesEx (dc, &font_match_pattern,
95 (FONTENUMPROC) add_opentype_font_name_to_list, 101 (FONTENUMPROC) add_opentype_font_name_to_list,
96 (LPARAM) &list, 0); 102 (LPARAM) &list, 0);
97 release_frame_dc (f, dc); 103 release_frame_dc (f, dc);
104 Vinhibit_quit = prev_quit;
98 105
99 return list; 106 return list;
100} 107}