Skip to content
Browse files

Detect object conflicts during deserialization.

If two pre-compiled modules both tried to replace an object or STable
with their own updated view of it, the latest one would always just
win. This creates the "disappearing symbol" issue. This patch detects
that it's going on and complains, rather than leaving a weird failure
later on (the actual fix will be to replace the exception thrown with
a hook to allow the module loader to do some smarter merging).

Breaks no NQP tests or Rakudo spectests; does correctly pick up the
RT#112626 case.
  • Loading branch information...
1 parent b0a8080 commit b5718034e4089eeaea9dab968337d921ae762811 @jnthn jnthn committed Nov 15, 2012
Showing with 16 additions and 6 deletions.
  1. +16 −6 src/6model/serialization.c
View
22 src/6model/serialization.c
@@ -1692,9 +1692,14 @@ static void repossess(PARROT_INTERP, SerializationReader *reader, INTVAL i) {
Parrot_Int4 repo_type = read_int32(table_row, 0);
if (repo_type == 0) {
/* Get object to repossess. */
- PMC *orig_obj = SC_get_object(interp,
- locate_sc(interp, reader, read_int32(table_row, 8)),
- read_int32(table_row, 12));
+ PMC *orig_sc = locate_sc(interp, reader, read_int32(table_row, 8));
+ PMC *orig_obj = SC_get_object(interp, orig_sc, read_int32(table_row, 12));
+
+ /* Make sure we don't have a reposession conflict. */
+ if (SC_PMC(orig_obj) != orig_sc)
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
+ "Object conflict detected during deserialization\n"
+ "(Probable attempt to load two modules that cannot be loaded together).");
/* Clear it up, since we'll re-allocate all the bits inside
* it on deserialization. */
@@ -1706,9 +1711,14 @@ static void repossess(PARROT_INTERP, SerializationReader *reader, INTVAL i) {
}
else if (repo_type == 1) {
/* Get STable to repossess. */
- PMC *orig_st = SC_get_stable(interp,
- locate_sc(interp, reader, read_int32(table_row, 8)),
- read_int32(table_row, 12));
+ PMC *orig_sc = locate_sc(interp, reader, read_int32(table_row, 8));
+ PMC *orig_st = SC_get_stable(interp, orig_sc, read_int32(table_row, 12));
+
+ /* Make sure we don't have a reposession conflict. */
+ if (STABLE_STRUCT(orig_st)->sc != orig_sc)
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
+ "STable conflict detected during deserialization.\n"
+ "(Probable attempt to load two modules that cannot be loaded together).");
/* Clear it up, since we'll re-allocate all the bits inside
* it on deserialization. */

0 comments on commit b571803

Please sign in to comment.
Something went wrong with that request. Please try again.