aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriains <iains@138bc75d-0d04-0410-961f-82ee72b054a4>2019-08-31 19:12:10 +0000
committeriains <iains@138bc75d-0d04-0410-961f-82ee72b054a4>2019-08-31 19:12:10 +0000
commit9e8c00d7acff8be1a29aed4793e9d9b7d56878b1 (patch)
treeb3e628ccf1583a01dfbbb5bf2679aff1b955ef0b
parent314827674a498df8a5b613fae1ec9bada2420269 (diff)
[c-family] Backport fix for PCH / PR61250.
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-9-branch@275246 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/c-family/ChangeLog9
-rw-r--r--gcc/c-family/c-lex.c7
-rw-r--r--gcc/c/ChangeLog10
-rw-r--r--gcc/c/c-parser.c2
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/parser.c5
-rw-r--r--gcc/ggc-page.c5
8 files changed, 48 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f3a53408f85..3ae23dbc01b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index acdfe79894e..8fa6963f186 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -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.
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index 0a368a33a58..3c92103a5d4 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -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;
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 89e5b25d020..b98aa517ff2 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -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.
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index f8d1fb3fa78..3b58dc368de 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -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;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index adc0a839708..da73772c99e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 58b44abd109..09251bf2135 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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)
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 143986be58f..cd531e5b1e6 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -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++)
{