[Python-Dev] Directions for reproducing the coredump

Eric S. Raymond esr@thyrsus.com
Fri, 11 Aug 2000 23:56:33 -0400


Here are the directions to reproduce the core dump.

1. Download and unpack CML2 version 0.7.6 from 
   <http://www.tuxedo.org/~esr/kbuild/>.  Change directory into it.

2. Do `cmlcompile.py kernel-rules.cml' to generate a pickled rulebase.

3. Run `make xconfig'.  Ignore the error message about the arch defconfig.

4. Set NETDEVICES on the main menu to 'y'.
5. Select the "Network Device Configuration" menu that appears below.
6. Set PPP to 'y'.
7. Select the "PPP options" menu that appears below it.
8. Set PPP_BSDCOMP to 'y'.

9. Observe and dismiss the pop-up window.  Quit the configurator using the
   "File" menu on the menu bar.

10. Now apply the attached patch.

11. Repeat steps 2-10.  

12. Observe the core dump.  If you look near cmlsystem.py:770, you'll see
    that the patch inserted two print statements that bracket the apparent
    point of the core dump.

13. To verify that this core dump is neither a Tkinter nor an ncurses problem,
    run `make menuconfig'.

14. Repeat steps 2-8.  To set symbols in the curses interface, use the arrow
    keys to select each one and type "y".  To select a menu, use the arrow
    keys and type a space or Enter when the selection bar is over the entry.

15. Observe the core dump at the same spot.

This bug bites both a stock 1.5.2 and today's CVS snapshoot of 2.0.

--- cml.py	2000/08/12 03:21:40	1.97
+++ cml.py	2000/08/12 03:25:45
@@ -111,6 +111,21 @@
         res = res + self.dump()
         return res[:-1] + "}"
 
+class Requirement:
+    "A requirement, together with a message to be shown if it's violated."
+    def __init__(self, wff, message=None):
+        self.predicate = wff
+        self.message = message
+
+    def str(self):
+        return display_expression(self.predicate)
+
+    def __repr__(self):
+        if self.message:
+            return self.message
+        else:
+            return str(self)
+
 # This describes an entire configuration.
 
 class CMLRulebase:
--- cmlcompile.py	2000/08/10 16:22:39	1.131
+++ cmlcompile.py	2000/08/12 03:24:31
@@ -12,7 +12,7 @@
 
 _keywords = ('symbols', 'menus', 'start', 'unless', 'suppress',
 	    'dependent', 'menu', 'choices', 'derive', 'default',
-	    'range', 'require', 'prohibit', 'private', 'debug',
+	    'range', 'require', 'prohibit', 'explanation', 'private', 'debug',
 	    'helpfile', 'prefix', 'banner', 'icon', 'condition',
 	    'trits', 'on', 'warndepend')
 
@@ -432,7 +432,14 @@
             expr = parse_expr(input)
             if leader.type == "prohibit":
                 expr = ('==', expr, cml.n.value)
-	    requirements.append(expr)	    
+            msg = None
+            #next = input.lex_token()
+            #if next.type != 'explanation':
+            #    input.push_token(next)
+            #    continue
+            #else:
+            #    msg = input.demand("word")
+	    requirements.append(cml.Requirement(expr, msg))	    
 	    bool_tests.append((expr, input.infile, input.lineno))
 	elif leader.type == "default":
 	    symbol = input.demand("word")
@@ -746,7 +753,7 @@
             entry.visibility = resolve(entry.visibility)
 	if entry.default:
 	    entry.default = resolve(entry.default)
-    requirements = map(resolve, requirements)
+    requirements = map(lambda x: cml.Requirement(resolve(x.predicate), x.message), requirements)
     if bad_symbols:
 	sys.stderr.write("cmlcompile: %d symbols could not be resolved:\n"%(len(bad_symbols),))
 	sys.stderr.write(`bad_symbols.keys()` + "\n")
@@ -868,7 +875,7 @@
     # rule file are not consistent, it's not likely the user will make
     # a consistent one.
     for wff in requirements:
-	if not cml.evaluate(wff, debug):
+	if not cml.evaluate(wff.predicate, debug):
 	    print "cmlcompile: constraint violation:", wff
 	    errors = 1
 
--- cmlsystem.py	2000/07/25 04:24:53	1.98
+++ cmlsystem.py	2000/08/12 03:29:21
@@ -28,6 +28,7 @@
     "INCAUTOGEN":"/*\n * Automatically generated, don't edit\n */\n",
     "INCDERIVED":"/*\n * Derived symbols\n */\n",
     "ISNOTSET":"# %s is not set\n",
+    "NOTRITS":"Trit values are not currently allowed.",
     "RADIOINVIS":"    Query of choices menu %s elided, button pressed",
     "READING":"Reading configuration from %s",
     "REDUNDANT":"    Redundant assignment forced by %s", 
@@ -100,10 +101,10 @@
         "Assign constraints to their associated symbols."
         for entry in self.dictionary.values():
             entry.constraints = []
-        for wff in self.constraints:
-            for symbol in cml.flatten_expr(wff):
-                if not wff in symbol.constraints:
-                    symbol.constraints.append(wff)
+        for requirement in self.constraints:
+            for symbol in cml.flatten_expr(requirement.predicate):
+                if not requirement.predicate in symbol.constraints:
+                    symbol.constraints.append(requirement)
         if self.debug:
             cc = dc = tc = 0
             for symbol in self.dictionary.values():
@@ -436,8 +437,8 @@
         if symbol.constraints:
             self.set_symbol(symbol, value)
             for constraint in symbol.constraints:
-                if not cml.evaluate(constraint, self.debug):
-                    self.debug_emit(1, self.lang["CONSTRAINT"] % (value, symbol.name, constraint))
+                if not cml.evaluate(constraint.predicate, self.debug):
+                    self.debug_emit(1, self.lang["CONSTRAINT"] % (value, symbol.name, str(constraint)))
                     self.rollback()
                     return 0
             self.rollback()
@@ -544,7 +545,7 @@
         # be unfrozen.  Simplify constraints to remove newly frozen variables.
         # Then rerun optimize_constraint_access.
         if freeze:
-            self.constraints = map(lambda wff, self=self: self.simplify(wff), self.constraints)
+            self.constraints = map(lambda requirement, self=self: cml.Requirement(self.simplify(requirement.predicate), requirement.message), self.constraints)
             self.optimize_constraint_access()
             for entry in self.dictionary.values():
                 if self.bindcheck(entry, self.newbindings) and entry.menu and entry.menu.type=="choices":
@@ -559,7 +560,7 @@
         violations = []
         # First, check the explicit constraints.
         for constraint in self.constraints:
-            if not cml.evaluate(constraint, self.debug):
+            if not cml.evaluate(constraint.predicate, self.debug):
                 violations.append(constraint);
                 self.debug_emit(1, self.lang["FAILREQ"] % (constraint,))
         # If trits are disabled, any variable having a trit value is wrong.
@@ -570,7 +571,7 @@
                     mvalued = ('and', ('!=', entry,cml.m), mvalued)
             if mvalued != cml.y:
                mvalued = self.simplify(mvalued)
-               violations.append(('implies', ('==', self.trit_tie, cml.n), mvalued))
+               violations.append(cml.Requirement(('implies', ('==', self.trit_tie, cml.n), mvalued), self.lang["NOTRITS"]))
         return violations
 
     def set_symbol(self, symbol, value, source=None):
@@ -631,10 +632,10 @@
         dups = {}
         relevant = []
         for csym in touched:
-            for wff in csym.constraints:
-                if not dups.has_key(wff):
-                    relevant.append(wff)
-                    dups[wff] = 1
+            for requirement in csym.constraints:
+                if not dups.has_key(requirement.predicate):
+                    relevant.append(requirement.predicate)
+                    dups[requirement.predicate] = 1
         # Now loop through the constraints, simplifying out assigned
         # variables and trying to freeze more variables each time.
         # The outer loop guarantees that as long as the constraints
@@ -765,7 +766,9 @@
                     else:
                         self.set_symbol(left, cml.n.value, source)
                         return 1
+                print "Just before the core-dump point"
                 if right_mutable and left == cml.n.value:
+                    print "Just after the core-dump point"
                     if rightnonnull == cml.n.value:
                         self.debug_emit(1, self.lang["REDUNDANT"] % (wff,))
                         return 0

End of diffs,

-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

A human being should be able to change a diaper, plan an invasion,
butcher a hog, conn a ship, design a building, write a sonnet, balance
accounts, build a wall, set a bone, comfort the dying, take orders, give
orders, cooperate, act alone, solve equations, analyze a new problem,
pitch manure, program a computer, cook a tasty meal, fight efficiently,
die gallantly. Specialization is for insects.
	-- Robert A. Heinlein, "Time Enough for Love"