]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[c-family] Backport fix for PCH / PR61250.
authorIain Sandoe <iain@sandoe.co.uk>
Sat, 31 Aug 2019 19:12:10 +0000 (19:12 +0000)
committerIain Sandoe <iains@gcc.gnu.org>
Sat, 31 Aug 2019 19:12:10 +0000 (19:12 +0000)
When we are parsing a source file, the very first token might
be a PRAGMA_GCC_PCH_PREPROCESS. This indicates that we are going
read in a PCH file (named as the value of the pragma). If we don't
see this pragma, then we know that it's OK to release any resources
that the host might have set aside for the PCH file.

There is a thinko in the current implementation, in that the decision
to release resources is happening unconditionally right after the first
token is extracted but before it's been checked or acted upon.

This leads to the pch bug on Darwin, because we actually do release
resources - which are subsequently (reasonably) assumed to be available
when reading a PCH file. We then get random crashes or hangs depending
on the interaction between unmmap and malloc.

The bug is present everywhere but doesn't show on (say) Linux, since
the release of PCH resources is a NOP there.

This effects all the c-family front ends, because they all use
c_lex_with_flags () to implement this.

The solution is to check for the PRAGMA_GCC_PCH_PREPROCESS and only call
c_common_no_more_pch () when that is not the first token.

A secondary effect of the collection is that the name of the PCH file
can be collected during the ggc_pch_read() reset of state. Therefore
we should issue any diagnostic that might name the file before the
collections are triggered.

gcc/

2019-08-31  Iain Sandoe  <iain@sandoe.co.uk>

Backport from mainline
2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>

PR pch/61250
* ggc-page.c (ggc_pch_read): Read the ggc_pch_ondisk structure
and issue any diagnostics needed before collecting the pre-PCH
state.

gcc/c-family/

2019-08-31  Iain Sandoe  <iain@sandoe.co.uk>

Backport from mainline
2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>

PR pch/61250
* c-lex.c (c_lex_with_flags):  Don't call
c_common_no_more_pch () from here.

gcc/c/

2019-08-31  Iain Sandoe  <iain@sandoe.co.uk>

Backport from mainline.
2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>

PR pch/61250
* c-parser.c (c_parse_file): Call c_common_no_more_pch ()
after determining that the first token is not
PRAGMA_GCC_PCH_PREPROCESS.

gcc/cp/

2019-08-31  Iain Sandoe  <iain@sandoe.co.uk>

Backported from mainline
2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>

PR pch/61250
* parser.c (cp_parser_initial_pragma): Call c_common_no_more_pch ()
after determining that the first token is not
PRAGMA_GCC_PCH_PREPROCESS.

From-SVN: r275246

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-lex.c
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/ggc-page.c

index f3a53408f85029d4556c7692f1e7875eb8409954..3ae23dbc01b902dfc1db9147b2e6bf2cb8b5f1ec 100644 (file)
@@ -1,3 +1,13 @@
+2019-08-31  Iain Sandoe  <iain@sandoe.co.uk>
+
+       Backport from mainline
+       2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>
+
+       PR pch/61250
+       * ggc-page.c (ggc_pch_read): Read the ggc_pch_ondisk structure
+       and issue any diagnostics needed before collecting the pre-PCH
+       state.
+
 2019-08-30  Segher Boessenkool  <segher@kernel.crashing.org>
 
        Backport from trunk
index acdfe79894eabb81e9c1c29fd1068d6ef06d7279..8fa6963f18622656b1a9e161413819c7a8916c5d 100644 (file)
@@ -1,3 +1,12 @@
+2019-08-31  Iain Sandoe  <iain@sandoe.co.uk>
+
+       Backport from mainline
+       2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>
+
+       PR pch/61250
+       * c-lex.c (c_lex_with_flags):  Don't call
+       c_common_no_more_pch () from here.
+
 2019-08-12  Release Manager
 
        * GCC 9.2.0 released.
index 0a368a33a5839fedab872850d14e4fdf3268b457..3c92103a5d4817834ff6ebca4ec12abfa6690af4 100644 (file)
@@ -394,7 +394,6 @@ enum cpp_ttype
 c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
                  int lex_flags)
 {
-  static bool no_more_pch;
   const cpp_token *tok;
   enum cpp_ttype type;
   unsigned char add_flags = 0;
@@ -628,12 +627,6 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
   if (cpp_flags)
     *cpp_flags = tok->flags | add_flags;
 
-  if (!no_more_pch)
-    {
-      no_more_pch = true;
-      c_common_no_more_pch ();
-    }
-
   timevar_pop (TV_CPP);
 
   return type;
index 89e5b25d020df496c700029bf17262c423cfe461..b98aa517ff23c8f297c1c11db5c6e6c8be344aa9 100644 (file)
@@ -1,3 +1,13 @@
+2019-08-31  Iain Sandoe  <iain@sandoe.co.uk>
+
+       Backport from mainline.
+       2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>
+
+       PR pch/61250
+       * c-parser.c (c_parse_file): Call c_common_no_more_pch ()
+       after determining that the first token is not
+       PRAGMA_GCC_PCH_PREPROCESS.
+
 2019-08-12  Release Manager
 
        * GCC 9.2.0 released.
index f8d1fb3fa7814d1625b497ecd5074c487674fa4d..3b58dc368deef1550b8fc7d1c439633a83059f55 100644 (file)
@@ -19859,6 +19859,8 @@ c_parse_file (void)
 
   if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
     c_parser_pragma_pch_preprocess (&tparser);
+  else
+    c_common_no_more_pch ();
 
   the_parser = ggc_alloc<c_parser> ();
   *the_parser = tparser;
index adc0a83970887332aad0eee9a1b9fa5aee3f6d5a..da73772c99e3f833c210857d4e5425f39f8a132b 100644 (file)
@@ -1,3 +1,13 @@
+2019-08-31  Iain Sandoe  <iain@sandoe.co.uk>
+
+       Backported from mainline
+       2019-08-23  Iain Sandoe  <iain@sandoe.co.uk>
+
+       PR pch/61250
+       * parser.c (cp_parser_initial_pragma): Call c_common_no_more_pch ()
+       after determining that the first token is not
+       PRAGMA_GCC_PCH_PREPROCESS.
+
 2019-08-23  Marek Polacek  <polacek@redhat.com>
 
        Backported from mainline
index 58b44abd1092bfb3123e3c2eef0da4ab29d4dc04..09251bf21356462c04cb392eccb7c0341dc7606c 100644 (file)
@@ -40751,7 +40751,10 @@ cp_parser_initial_pragma (cp_token *first_token)
 
   cp_lexer_get_preprocessor_token (NULL, first_token);
   if (cp_parser_pragma_kind (first_token) != PRAGMA_GCC_PCH_PREPROCESS)
-    return;
+    {
+      c_common_no_more_pch ();
+      return;
+    }
 
   cp_lexer_get_preprocessor_token (NULL, first_token);
   if (first_token->type == CPP_STRING)
index 143986be58f75f3f15b927dc5113006da53e91d9..cd531e5b1e6b2bf01e48a83f5e41ce7f379c953d 100644 (file)
@@ -2556,6 +2556,9 @@ ggc_pch_read (FILE *f, void *addr)
 
   count_old_page_tables = G.by_depth_in_use;
 
+  if (fread (&d, sizeof (d), 1, f) != 1)
+    fatal_error (input_location, "cannot read PCH file: %m");
+
   /* We've just read in a PCH file.  So, every object that used to be
      allocated is now free.  */
   clear_marks ();
@@ -2584,8 +2587,6 @@ ggc_pch_read (FILE *f, void *addr)
 
   /* Allocate the appropriate page-table entries for the pages read from
      the PCH file.  */
-  if (fread (&d, sizeof (d), 1, f) != 1)
-    fatal_error (input_location, "can%'t read PCH file: %m");
 
   for (i = 0; i < NUM_ORDERS; i++)
     {