VoIP.info Guide

Asterisk dialplan locks: serialize shared state without hiding call failure

Use LOCK, TRYLOCK and UNLOCK around the smallest shared-state update, preserve channel ownership and failure branches, and keep the protected operation distinct from mutex acquisition.

Reviewed 2026-10-19Asterisk Latest API branch 23 LOCK, TRYLOCK and UNLOCK documentation, Asterisk 22 SHARED documentation and current global-variable guidance reviewed October 14, 2026; function availability, loaded func_lock and func_global modules, exact lock names, channel ownership, protected data, wait duration, dialplan branches and external side effects remain deployment specific; no PBX, module, dialplan, channel, lock, variable, database row, file, external service or call was inspected or testedAdvancedDocumentation based · not lab tested

Lock one invariant, not an entire call

LOCK(name) waits for exclusive ownership of one named mutex, while TRYLOCK(name) returns immediately when that mutex is unavailable. Both return 1 when obtained and 0 otherwise. The result proves only lock acquisition; it does not prove that a shared-variable update, database operation, file write, external request or call branch succeeded.

Name the invariant before adding a mutex: for example, allocating one scarce identifier or updating a read-modify-write counter. Keep prompts, dialing, network requests and unrelated calculations outside the critical section so one slow call does not serialize other channels unnecessarily.

Choose blocking or explicit contention handling

Use LOCK() only when bounded waiting is acceptable to the caller and every exit path is understood. Asterisk documents a special three-second attempt when the same channel already holds another lock, reducing one deadlock risk without proving that arbitrary lock ordering is safe.

Use TRYLOCK() when the dialplan must choose immediately among retry, queue, alternate destination, unchanged read or explicit failure. A zero result is contention or error evidence, not permission to enter the protected section anyway. Record the exact branch taken and the caller treatment that follows.

Keep lock name, channel and data scope aligned

The lock is named, while ownership belongs to the executing channel. Derive names only from bounded, normalized identifiers; an accidental per-call suffix defeats mutual exclusion, while one global name can turn unrelated tenants or resources into a single bottleneck. Do not place untrusted caller text directly into an administrative naming scheme.

SHARED() values occupy a namespace separate from ordinary channel variables and can change without warning when other channels write them. Global variables apply across calls. A named lock does not automatically bind either store: every reader and writer participating in the invariant must use the same lock contract.

Protect the complete read-modify-write sequence

Acquire the mutex, verify the success result, read the shared value into an ordinary channel variable, validate it, compute the new value, commit the update, verify the write and release the same name. Locking only the write still allows two channels to read the same old value and produce a lost update.

Keep database transactions, AstDB operations, files and remote services attached to their own commit evidence. A mutex inside one Asterisk process does not establish cross-node serialization, durable storage, remote idempotency or cluster consensus.

Release deliberately on every normal branch

UNLOCK(name) returns 1 when the channel held a lock and 0 otherwise. Treat an unexpected zero as evidence of mismatched naming, ownership or control flow. Asterisk says held locks are automatically freed when the channel is destroyed, but that cleanup boundary is not a substitute for releasing after the protected operation.

Keep the release immediately visible in the same subroutine or use a single cleanup branch that every acquired path reaches. Never attempt an unlock from a sibling channel merely because it shares a linked ID, and do not rely on hangup cleanup to shorten a long-lived call.

Prove contention, state and caller outcome separately

For an authorized test, launch a small controlled overlap against a non-production key. Record channel IDs, lock name, acquisition result, wait interval, state before and after, write result, unlock result and final dialplan destination. Include an uncontended control and a deliberately failed protected operation.

Keep live_dangerously=no unless a reviewed integration requires otherwise; the functions document that this setting confines direct execution to dialplan rather than external protocols. This guide is documentation-derived. No PBX, lock, variable, external resource or call was tested.

Protect multi-step AstDB invariants separately

An AstDB key can persist locally, but a read-modify-write sequence still needs one shared mutex contract. Use the AstDB guide for storage semantics and this guide for local serialization.

Do not mistake one database connection for transaction safety

The func_odbc guide keeps connection reuse, database transactions, local dialplan locks and caller treatment as separate contracts.

Keep a dialplan lock distinct from a database transaction

The ODBC transaction guide treats local serialization, database isolation, schema constraints and idempotency as different controls.

A shared condition still needs one protected invariant

The WaitForCondition guide does not treat polling, a linked ID or a similarly named value as cross-channel synchronization.

Do not turn a changing key list into hidden shared state

The HASH and ARRAY guide snapshots HASHKEYS before mutation and reserves persistent or cross-call ownership for an explicit shared-state design.

Do not turn Setvar into an unlocked shared-state update

The AMI variable diagnostic checks namespace and concurrent writers before accepting a shared or global value.

Coordinate AMI and dialplan writers

The AMI AstDB guide treats local persistence as separate from concurrency and application-level ownership.

Sources & applicability

Primary references for the technical details above. Operational examples and planning checklists are VoIP.info editorial guidance.

Examples require adaptation to your topology. No live PBX or hardware testing is claimed.