Raymond Toy pushed to branch issue-500-common-package-error-restart-function at cmucl / cmucl

Commits:

3 changed files:

Changes:

  • src/code/macros.lisp
    ... ... @@ -222,7 +222,7 @@
    222 222
       (unless (symbolp name)
    
    223 223
         (simple-program-error (intl:gettext "~S -- Type name not a symbol.") name))
    
    224 224
       (let ((pkg (symbol-package name)))
    
    225
    -    (when pkg
    
    225
    +    (when (and pkg (ext:package-definition-lock pkg))
    
    226 226
           (signal-package-locked-error pkg :definition
    
    227 227
     				   (intl:gettext "defining type ~A")
    
    228 228
     				   name)))
    

  • src/code/package.lisp
    ... ... @@ -195,8 +195,7 @@
    195 195
     (defun signal-package-locked-error (package lock-kind message-control &rest message-args)
    
    196 196
       (when (and (boundp 'lisp::*enable-package-locked-errors*)
    
    197 197
     	     lisp::*enable-package-locked-errors*)
    
    198
    -    (when (ext:package-definition-lock package)
    
    199
    -      (restart-case
    
    198
    +    (restart-case
    
    200 199
               (error 'lisp::package-locked-error
    
    201 200
                      :package package
    
    202 201
                      :format-control message-control
    
    ... ... @@ -217,7 +216,7 @@
    217 216
             (unlock-all ()
    
    218 217
               :report (lambda (stream)
    
    219 218
     		    (write-string (intl:gettext "Unlock all packages, then continue") stream))
    
    220
    -          (unlock-all-packages))))))
    
    219
    +          (unlock-all-packages)))))
    
    221 220
     
    
    222 221
     ;; trap attempts to redefine a function in a locked package, and
    
    223 222
     ;; signal a continuable error.
    
    ... ... @@ -1488,9 +1487,10 @@
    1488 1487
     	 (name (symbol-name symbol))
    
    1489 1488
     	 (shadowing-symbols (package-%shadowing-symbols package)))
    
    1490 1489
         (declare (list shadowing-symbols) (simple-string name))
    
    1491
    -    (signal-package-locked-error package :namespace
    
    1490
    +    (when (ext:package-lock package)
    
    1491
    +      (signal-package-locked-error package :namespace
    
    1492 1492
     				 (intl:gettext "uninterning symbol ~A")
    
    1493
    -				 name)
    
    1493
    +				 name))
    
    1494 1494
         #+nil
    
    1495 1495
         (when *enable-package-locked-errors*
    
    1496 1496
           (when (ext:package-lock package)
    
    ... ... @@ -1674,9 +1674,10 @@
    1674 1674
       "Makes SYMBOLS no longer exported from PACKAGE."
    
    1675 1675
       (let ((package (package-or-lose package))
    
    1676 1676
     	(syms ()))
    
    1677
    -    (signal-package-locked-error package :namespace
    
    1678
    -				 (intl:gettext "unexporting symbols ~A")
    
    1679
    -				 symbols)
    
    1677
    +    (when (ext:package-lock package)
    
    1678
    +      (signal-package-locked-error package :namespace
    
    1679
    +				   (intl:gettext "unexporting symbols ~A")
    
    1680
    +				   symbols))
    
    1680 1681
         #+nil
    
    1681 1682
         (when *enable-package-locked-errors*
    
    1682 1683
           (when (ext:package-lock package)
    

  • tests/package-lock.lisp
    1
    +;;; Regression tests for package-locked-error signaling.
    
    2
    +;;;
    
    3
    +;;; These tests exist as a baseline before refactoring the
    
    4
    +;;; package-lock checks into a shared helper.  They verify that
    
    5
    +;;; package-locked-error is signaled at each call site we expect to
    
    6
    +;;; check the lock; restart behavior is tested separately.
    
    7
    +
    
    8
    +(defpackage :package-lock-tests
    
    9
    +  (:use :cl :lisp-unit))
    
    10
    +
    
    11
    +(in-package "PACKAGE-LOCK-TESTS")
    
    12
    +
    
    13
    +(defpackage :test-locked-package
    
    14
    +  (:use :cl))
    
    15
    +
    
    16
    +(let* ((p (find-package :test-locked-package))
    
    17
    +       (sym (intern "TOPLEVEL-PROBE" p)))
    
    18
    +  (setf (ext:package-lock p) t)
    
    19
    +  (format t "~&TOPLEVEL: package-lock=~S enable=~S~%"
    
    20
    +          (ext:package-lock p) lisp::*enable-package-locked-errors*)
    
    21
    +  (handler-case
    
    22
    +      (let ((result (unintern sym p)))
    
    23
    +        (format t "~&TOPLEVEL: unintern returned ~S (no error)~%" result))
    
    24
    +    (lisp::package-locked-error (c)
    
    25
    +      (format t "~&TOPLEVEL: caught error ~A~%" c))
    
    26
    +    (error (c)
    
    27
    +      (format t "~&TOPLEVEL: caught other error ~A (~A)~%" c (type-of c))))
    
    28
    +  (setf (ext:package-lock p) nil))
    
    29
    +
    
    30
    +(defmacro with-definition-locked ((package) &body body)
    
    31
    +  "Run BODY with PACKAGE's definition-lock enabled and namespace-lock
    
    32
    +   disabled, so failures from BODY can be attributed unambiguously to
    
    33
    +   the definition lock."
    
    34
    +  `(let ((p ,package))
    
    35
    +     (setf (ext:package-definition-lock p) t
    
    36
    +           (ext:package-lock p) nil)
    
    37
    +     (assert-true (ext:package-definition-lock p))
    
    38
    +     (assert-false (ext:package-lock p))
    
    39
    +     (unwind-protect (progn ,@body)
    
    40
    +       (setf (ext:package-definition-lock p) nil
    
    41
    +             (ext:package-lock p) nil))))
    
    42
    +
    
    43
    +(defmacro with-namespace-locked ((package) &body body)
    
    44
    +  "Run BODY with PACKAGE's namespace-lock enabled and definition-lock
    
    45
    +   disabled, so failures from BODY can be attributed unambiguously to
    
    46
    +   the namespace lock."
    
    47
    +  `(let ((p ,package))
    
    48
    +     (setf (ext:package-definition-lock p) nil
    
    49
    +           (ext:package-lock p) t)
    
    50
    +     (assert-false (ext:package-definition-lock p))
    
    51
    +     (assert-true (ext:package-lock p))
    
    52
    +     (unwind-protect (progn ,@body)
    
    53
    +       (setf (ext:package-definition-lock p) nil
    
    54
    +             (ext:package-lock p) nil))))
    
    55
    +
    
    56
    +
    
    57
    +;;; ---- Definition-lock tests ----
    
    58
    +
    
    59
    +(define-test package-locked.defmacro
    
    60
    +  (:tag :issues)
    
    61
    +  (with-definition-locked ((find-package :test-locked-package))
    
    62
    +    (assert-error 'lisp::package-locked-error
    
    63
    +                  (eval '(defmacro test-locked-package::a-macro (x)
    
    64
    +                          `(list ,x))))))
    
    65
    +
    
    66
    +(define-test package-locked.defun
    
    67
    +  (:tag :issues)
    
    68
    +  (with-definition-locked ((find-package :test-locked-package))
    
    69
    +    (assert-error 'lisp::package-locked-error
    
    70
    +                  (eval '(defun test-locked-package::a-fn (x) x)))))
    
    71
    +
    
    72
    +(define-test package-locked.deftype
    
    73
    +  (:tag :issues)
    
    74
    +  (with-definition-locked ((find-package :test-locked-package))
    
    75
    +    (assert-error 'lisp::package-locked-error
    
    76
    +                  (eval '(deftype test-locked-package::a-type ()
    
    77
    +                          'integer)))))
    
    78
    +
    
    79
    +(define-test package-locked.defstruct
    
    80
    +  (:tag :issues)
    
    81
    +  (with-definition-locked ((find-package :test-locked-package))
    
    82
    +    (assert-error 'lisp::package-locked-error
    
    83
    +                  (eval '(defstruct test-locked-package::a-struct
    
    84
    +                          slot-1 slot-2)))))
    
    85
    +
    
    86
    +
    
    87
    +;;; ---- Namespace-lock tests ----
    
    88
    +
    
    89
    +(define-test package-locked.unintern
    
    90
    +  (:tag :issues)
    
    91
    +  (let ((sym (intern "TO-BE-UNINTERNED"
    
    92
    +                     (find-package :test-locked-package))))
    
    93
    +    (with-namespace-locked ((find-package :test-locked-package))
    
    94
    +      (assert-error 'lisp::package-locked-error
    
    95
    +                    (unintern sym (find-package :test-locked-package))))))
    
    96
    +
    
    97
    +(define-test package-locked.unexport
    
    98
    +  (:tag :issues)
    
    99
    +  (let* ((p (find-package :test-locked-package))
    
    100
    +         (sym (intern "TO-BE-UNEXPORTED" p)))
    
    101
    +    (export sym p)
    
    102
    +    (with-namespace-locked (p)
    
    103
    +      (assert-error 'lisp::package-locked-error
    
    104
    +                    (unexport sym p)))))
    
    105
    +
    
    106
    +(define-test package-lock-debug
    
    107
    +  (:tag :issues)
    
    108
    +  (let* ((p (find-package :test-locked-package))
    
    109
    +         (sym (intern "DEBUG-SYM" p)))
    
    110
    +    (setf (ext:package-lock p) t)
    
    111
    +    (format t "~&Just before unintern:~%")
    
    112
    +    (format t "  package-lock: ~S~%" (ext:package-lock p))
    
    113
    +    (format t "  *enable-package-locked-errors*: ~S~%"
    
    114
    +            lisp::*enable-package-locked-errors*)
    
    115
    +    (format t "  *package*: ~S~%" *package*)
    
    116
    +    (format t "  package of unintern fn: ~S~%"
    
    117
    +            (symbol-package 'unintern))
    
    118
    +    (handler-case
    
    119
    +        (let ((result (unintern sym p)))
    
    120
    +          (format t "  unintern returned: ~S~%" result))
    
    121
    +      (lisp::package-locked-error (c)
    
    122
    +        (format t "  GOT package-locked-error: ~A~%" c))
    
    123
    +      (error (c)
    
    124
    +        (format t "  got OTHER error: ~A~%" c)))
    
    125
    +    (setf (ext:package-lock p) nil)
    
    126
    +    (assert-true t)))
    
    127
    +
    
    128
    +;; At end of file:
    
    129
    +(format *error-output* "~&~%==== TOPLEVEL PROBE ====~%")
    
    130
    +(force-output *error-output*)
    
    131
    +(let* ((p (find-package :test-locked-package))
    
    132
    +       (sym (intern "TOPLEVEL-PROBE" p)))
    
    133
    +  (setf (ext:package-lock p) t)
    
    134
    +  (format *error-output* "package-lock=~S enable=~S~%"
    
    135
    +          (ext:package-lock p) lisp::*enable-package-locked-errors*)
    
    136
    +  (force-output *error-output*)
    
    137
    +  (handler-case
    
    138
    +      (let ((result (unintern sym p)))
    
    139
    +        (format *error-output* "unintern returned ~S (NO ERROR!)~%" result))
    
    140
    +    (lisp::package-locked-error (c)
    
    141
    +      (format *error-output* "GOT package-locked-error: ~A~%" c))
    
    142
    +    (error (c)
    
    143
    +      (format *error-output* "got OTHER error: ~A (~A)~%" c (type-of c))))
    
    144
    +  (force-output *error-output*)
    
    145
    +  (setf (ext:package-lock p) nil))
    
    146
    +(format *error-output* "==== END PROBE ====~%~%")
    
    147
    +(force-output *error-output*)