Document watchpoints

* doc/lispref/debugging.texi (Variable Debugging):
* doc/lispref/variables.texi (Watching Variables): New section.
* etc/NEWS: Add entry for watchpoints
This commit is contained in:
Noam Postavsky 2015-12-13 14:47:58 -05:00
parent e7cd98b86f
commit 56c817837b
5 changed files with 108 additions and 0 deletions

View file

@ -69,6 +69,7 @@ debugger recursively. @xref{Recursive Editing}.
* Error Debugging:: Entering the debugger when an error happens.
* Infinite Loops:: Stopping and debugging a program that doesn't exit.
* Function Debugging:: Entering it when a certain function is called.
* Variable Debugging:: Entering it when a variable is modified.
* Explicit Debug:: Entering it at a certain point in the program.
* Using Debugger:: What the debugger does; what you see while in it.
* Debugger Commands:: Commands used while in the debugger.
@ -290,6 +291,36 @@ Calling @code{cancel-debug-on-entry} does nothing to a function which is
not currently set up to break on entry.
@end deffn
@node Variable Debugging
@subsection Entering the debugger when a variable is modified
@cindex variable write debugging
@cindex debugging changes to variables
Sometimes a problem with a function is due to a wrong setting of a
variable. Setting up the debugger to trigger whenever the variable is
changed is a quick way to find the origin of the setting.
@deffn Command debug-on-variable-change variable
This function arranges for the debugger to be called whenever
@var{variable} is modified.
It is implemented using the watchpoint mechanism, so it inherits the
same characteristics and limitations: all aliases of @var{variable}
will be watched together, only dynamic variables can be watched, and
changes to the objects referenced by variables are not detected. For
details, see @ref{Watching Variables}.
@end deffn
@deffn Command cancel-debug-on-variable-change &optional variable
This function undoes the effect of @code{debug-on-variable-change} on
@var{variable}. When called interactively, it prompts for
@var{variable} in the minibuffer. If @var{variable} is omitted or
@code{nil}, it cancels break-on-change for all variables. Calling
@code{cancel-debug-on-variable-change} does nothing to a variable
which is not currently set up to break on change.
@end deffn
@node Explicit Debug
@subsection Explicit Entry to the Debugger
@cindex debugger, explicit entry

View file

@ -498,6 +498,7 @@ Variables
* Accessing Variables:: Examining values of variables whose names
are known only at run time.
* Setting Variables:: Storing new values in variables.
* Watching Variables:: Running a function when a variable is changed.
* Variable Scoping:: How Lisp chooses among local and global values.
* Buffer-Local Variables:: Variable values in effect only in one buffer.
* File Local Variables:: Handling local variable lists in files.
@ -642,6 +643,7 @@ The Lisp Debugger
* Error Debugging:: Entering the debugger when an error happens.
* Infinite Loops:: Stopping and debugging a program that doesn't exit.
* Function Debugging:: Entering it when a certain function is called.
* Variable Debugging:: Entering it when a variable is modified.
* Explicit Debug:: Entering it at a certain point in the program.
* Using Debugger:: What the debugger does; what you see while in it.
* Debugger Commands:: Commands used while in the debugger.

View file

@ -34,6 +34,7 @@ representing the variable.
* Accessing Variables:: Examining values of variables whose names
are known only at run time.
* Setting Variables:: Storing new values in variables.
* Watching Variables:: Running a function when a variable is changed.
* Variable Scoping:: How Lisp chooses among local and global values.
* Buffer-Local Variables:: Variable values in effect only in one buffer.
* File Local Variables:: Handling local variable lists in files.
@ -766,6 +767,66 @@ error is signaled.
@end example
@end defun
@node Watching Variables
@section Running a function when a variable is changed.
@cindex variable watchpoints
@cindex watchpoints for Lisp variables
It is sometimes useful to take some action when a variable changes its
value. The watchpoint facility provides the means to do so. Some
possible uses for this feature include keeping display in sync with
variable settings, and invoking the debugger to track down unexpected
changes to variables (@pxref{Variable Debugging}).
The following functions may be used to manipulate and query the watch
functions for a variable.
@defun add-variable-watcher symbol watch-function
This function arranges for @var{watch-function} to be called whenever
@var{symbol} is modified. Modifications through aliases
(@pxref{Variable Aliases}) will have the same effect.
@var{watch-function} will be called with 4 arguments: (@var{symbol}
@var{newval} @var{operation} @var{where}).
@var{symbol} is the variable being changed.
@var{newval} is the value it will be changed to.
@var{operation} is a symbol representing the kind of change, one of:
`set', `let', `unlet', `makunbound', and `defvaralias'.
@var{where} is a buffer if the buffer-local value of the variable is
being changed, nil otherwise.
@end defun
@defun remove-variable-watch symbol watch-function
This function removes @var{watch-function} from @var{symbol}'s list of
watchers.
@end defun
@defun get-variable-watchers symbol
This function returns the list of @var{symbol}'s active watcher
functions.
@end defun
@subsection Limitations
There are a couple of ways in which a variable could be modifed (or at
least appear to be modified) without triggering a watchpoint.
Since watchpoints are attached to symbols, modification to the
objects contained within variables (e.g., by a list modification
function @pxref{Modifying Lists}) is not caught by this mechanism.
Additionally, C code can modify the value of variables directly,
bypassing the watchpoint mechanism.
A minor limitation of this feature, again because it targets symbols,
is that only variables of dynamic scope may be watched. This poses
little difficulty, since modifications to lexical variables can be
discovered easily by inspecting the code within the scope of the
variable (unlike dynamic variables, which can be modified by any code
at all, @pxref{Variable Scoping}).
@node Variable Scoping
@section Scoping Rules for Variable Bindings
@cindex scoping rule

View file

@ -715,6 +715,11 @@ two objects are 'eq' ('eql'), then the result of 'sxhash-eq'
consistency with the new functions. For compatibility, 'sxhash'
remains as an alias to 'sxhash-equal'.
+++
** New function `add-variable-watcher' can be used to call a function
when a symbol's value is changed. This is used to implement the new
debugger command `debug-on-variable-change'.
+++
** Time conversion functions that accept a time zone rule argument now
allow it to be OFFSET or a list (OFFSET ABBR), where the integer

View file

@ -1428,6 +1428,15 @@ harmonize_variable_watchers (Lisp_Object alias, Lisp_Object base_variable)
DEFUN ("add-variable-watcher", Fadd_variable_watcher, Sadd_variable_watcher,
2, 2, 0,
doc: /* Cause WATCH-FUNCTION to be called when SYMBOL is set.
It will be called with 4 arguments: (SYMBOL NEWVAL OPERATION WHERE).
SYMBOL is the variable being changed.
NEWVAL is the value it will be changed to.
OPERATION is a symbol representing the kind of change, one of: `set',
`let', `unlet', `makunbound', and `defvaralias'.
WHERE is a buffer if the buffer-local value of the variable being
changed, nil otherwise.
All writes to aliases of SYMBOL will call WATCH-FUNCTION too. */)
(Lisp_Object symbol, Lisp_Object watch_function)
{