Skip to content

Latest commit

 

History

History
449 lines (288 loc) · 14.7 KB

error.rst

File metadata and controls

449 lines (288 loc) · 14.7 KB

single: error handling; introduction single: result code

Error handing

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.

Result codes

single: assertion single: error handling; assertion

Assertions

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

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 and rash 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

Common assertions and their 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 :cmps_reserve twice on the same allocation point without calling :cmps_commit. See topic-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 :cmps_pool_create_k for a pool class like pool-amc that requires a object format, but passed something other than a :cmps_fmt_t for this argument.

format.c: format->poolCount == 0

The client program called :cmps_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 :cmps_arena_destroy without destroying all the generation chains belonging to the arena. It is necessary to call :cmps_chain_destroy first.

global.c: RingIsSingle(&arena->formatRing)

The client program called :cmps_arena_destroy without destroying all the object formats belonging to the arena. It is necessary to call :cmps_fmt_destroy first.

global.c: RingIsSingle(&arenaGlobals->rootRing)

The client program called :cmps_arena_destroy without destroying all the roots belonging to the arena. It is necessary to call :cmps_root_destroy first.

global.c: RingIsSingle(&arena->threadRing)

The client program called :cmps_arena_destroy without deregistering all the threads belonging to the arena. It is necessary to call :cmps_thread_dereg first.

global.c: RingLength(&arenaGlobals->poolRing) == arenaGlobals->systemPools

The client program called :cmps_arena_destroy without destroying all the pools belonging to the arena. It is necessary to call :cmps_pool_destroy first.

global.c: PoolHasAttr(pool, AttrGC)

The client program called :cmps_finalize on a reference that does not belong to an automatically 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 :cmps_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 :cmps_reserve but neglected to round the size up to the alignment required by the pool's object format.

poolams.c: AMS_ALLOCED(seg, i)

The client program tried to fix a reference to a block in an pool-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 a formatted 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 under topic-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. See topic-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

Varieties

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