single: error handling; introduction single: result code
Operations in the Memory Pool System that might fail return a result code
of type :cmps_res_t
. Success is always indicated by the result code :cMPS_RES_OK
, which is defined to be zero. Other result codes indicate failure, and are non-zero. The MPS never uses a "special value" of some other type to indicate failure (such as returning NULL
for a pointer result, or −1 for a size result).
Note
The MPS does not throw or catch exceptions. (This is necessary for the MPS to be portable to systems that have only a freestanding
implementation of the C language.)
The modular nature of the MPS means that it is not usually possible for a function description to list the possible error codes that it might return. A function in the public interface typically calls methods of an arena class
and one or more pool
classes
, any of which might fail. The MPS is extensible with new arena and pool classes, which might fail in new and interesting ways, so the only future-proof behaviour is for a client program
to assume that any MPS function that returns a result code can return any result code.
single: assertion single: error handling; assertion
Bugs in the client program
may violate the invariants that the MPS relies on. Most functions in the MPS (in most varieties; see below) assert the correctness of their data structures, so these bugs will often be discovered by an assertion failure in the MPS. The section topic-error-cause
below lists commonly encountered assertions and explains the kinds of client program bugs that can provoke these assertions.
It is very rare for an assertion to indicate a bug in the MPS rather than the client program, but it is not unknown, so if you have made every effort to track down the cause (see guide-debug
) without luck, get in touch <contact>
.
single: assertion single: error handling; assertion; assertion handling
When the MPS detects an assertion failure, it calls the plinth
function :cmps_lib_assert_fail
. Unless you have replaced the plinth, this behaves as follows:
- In the
cool
variety
, print the assertion message to standard error and terminate the program by calling :cabort
. - In the
hot
andrash
varieties, print the assertion message to standard error and do not terminate the program.
You can change this behaviour by providing your own plinth, or using :cmps_lib_assert_fail_install
.
In many applications, users don't want their program terminated when the MPS detects an error, no matter how severe. A lot of MPS assertions indicate that the program is going to crash very soon, but there still may be a chance for a user to get some useful results or save their work. This is why the default assertion handler only terminates in the cool
variety
.
single: assertion; common causes
This section lists some commonly encountered assertions and suggests likely causes. If you encounter an assertion not listed here (or an assertion that is listed here but for which you discovered a different cause), please let us know <contact>
so that we can improve this documentation.
arg.c: MPS_KEY_...
A required
keyword argument
was omitted from a call to :cmps_ap_create_k
, :cmps_arena_create_k
, :cmps_fmt_create_k
, or :cmps_pool_create_k
.
buffer.c: BufferIsReady(buffer)
The client program called :c
mps_reserve
twice on the sameallocation point
without calling :cmps_commit
. Seetopic-allocation-point-protocol
.
dbgpool.c: fencepost check on free
The client program wrote to a location after the end, or before the beginning of an allocated block. See
topic-debugging
.
dbgpool.c: free space corrupted on release
The client program used an object after it was reclaimed. See
topic-debugging
.
format.c: SigCheck Format: format
The client program called :c
mps_pool_create_k
for apool class
likepool-amc
that requires aobject format
, but passed something other than a :cmps_fmt_t
for this argument.
format.c: format->poolCount == 0
The client program called :c
mps_fmt_destroy
on a format that was still being used by a pool. It is necessary to call :cmps_pool_destroy
first.
global.c: RingIsSingle(&arena->chainRing)
The client program called :c
mps_arena_destroy
without destroying all thegeneration chains
belonging to the arena. It is necessary to call :cmps_chain_destroy
first.
global.c: RingIsSingle(&arena->formatRing)
The client program called :c
mps_arena_destroy
without destroying all theobject formats
belonging to the arena. It is necessary to call :cmps_fmt_destroy
first.
global.c: RingIsSingle(&arenaGlobals->rootRing)
The client program called :c
mps_arena_destroy
without destroying all theroots
belonging to the arena. It is necessary to call :cmps_root_destroy
first.
global.c: RingIsSingle(&arena->threadRing)
The client program called :c
mps_arena_destroy
without deregistering all thethreads
belonging to the arena. It is necessary to call :cmps_thread_dereg
first.
global.c: RingLength(&arenaGlobals->poolRing) == arenaGlobals->systemPools
The client program called :c
mps_arena_destroy
without destroying all thepools
belonging to the arena. It is necessary to call :cmps_pool_destroy
first.
global.c: PoolHasAttr(pool, AttrGC)
The client program called :c
mps_finalize
on a reference that does not belong to anautomatically managed <automatic memory management>
pool
.
lockix.c: res == 0
lockw3.c: lock->claims == 0
The client program has made a re-entrant call into the MPS. Look at the backtrace to see what it was. Common culprits are signal handlers, assertion handlers, and
format methods
.
locus.c: gen->activeTraces == TraceSetEMPTY
The client program called :c
mps_chain_destroy
, but there was a garbage collection in progress on that chain. Park the arena before destroying the chain, by calling :cmps_arena_park
.
mpsi.c: SizeIsAligned(size, BufferPool(buf)->alignment)
The client program reserved a block by calling :c
mps_reserve
but neglected to round the size up to the alignment required by the pool'sobject format
.
poolams.c: AMS_ALLOCED(seg, i)
The client program tried to
fix
areference
to a block in anpool-ams
pool that died. This may mean that there was a previous collection in which a reference that should have kept the block alive failed to be scanned. Perhaps aformatted object
was updated in some way that has a race condition?
poolsnc.c: foundSeg
The client program passed an incorrect
frame
argument to :cmps_ap_frame_pop
. This argument must be the result from a previous call to :cmps_ap_frame_push
on the same allocation point.
seg.c: gcseg->buffer == NULL
The client program destroyed a pool without first destroying all the allocation points created on that pool. The allocation points must be destroyed first.
trace.c: ss->rank < RankEXACT
The client program destroyed a pool containing objects registered for finalization, and then continued to run the garbage collector. See
topic-finalization-cautions
undertopic-finalization
, which says, "You must destroy these pools by following the ‘safe tear-down’ procedure described under :cmps_pool_destroy
."
trace.c: RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg))
The client program's
scan method
failed to update a reference to an object that moved. Seetopic-scanning-protocol
, which says, "If :cMPS_FIX2
returns :cMPS_RES_OK
, it may have updated the reference. Make sure that the updated reference is stored back to the region being scanned."
single: error handling; varieties single: variety
The MPS has three varieties which have different levels of internal checking, topic-error-assertion
and topic-telemetry
. The variety can be selected at compile time, by defining one of the following preprocessor constants. If none is specified then :cCONFIG_VAR_HOT
is the default.
single: cool variety single: variety; cool
single: hot variety single: variety; hot
single: rash variety single: variety; rash