channel_call - send a message to a channel and await a reply


#include <zircon/syscalls.h>

typedef struct {
    void* wr_bytes;
    zx_handle_t* wr_handles;
    void *rd_bytes;
    zx_handle_t* rd_handles;
    uint32_t wr_num_bytes;
    uint32_t wr_num_handles;
    uint32_t rd_num_bytes;
    uint32_t rd_num_handles;
} zx_channel_call_args_t;

zx_status_t zx_channel_call(zx_handle_t handle, uint32_t options,
                            zx_time_t deadline, zx_channel_call_args_t* args,
                            uint32_t* actual_bytes, uint32_t* actual_handles,
                            zx_status_t* read_status);


channel_call() is like a combined channel_write(), object_wait_one(), and channel_read(), with the addition of a feature where a transaction id at the front of the message payload bytes is used to match reply messages with send messages, enabling multiple calling threads to share a channel without any additional userspace bookkeeping.

The write and read phases of this operation behave like channel_write() and channel_read() with the difference that their parameters are provided via the zx_channel_call_args_t structure.

The first four bytes (i.e., a leading zx_txid_t) of wr_bytes are considered to be the transaction id (txid). If there are fewer than four bytes, the txid is considered to be zero.

When the outbound message is written, simultaneously an interest is registered for inbound messages of the matching txid.

While deadline has not passed, if an inbound message arrives with a matching txid, instead of being added to the tail of the general inbound message queue, it is delivered directly to the thread waiting in zx_channel_call().

If such a reply arrives after deadline has passed, it will arrive in the general inbound message queue, cause ZX_CHANNEL_READABLE to be signaled, etc.

Inbound messages that are too large to fit in rd_num_bytes and rd_num_handles are discarded and ZX_ERR_BUFFER_TOO_SMALL is returned in that case.


channel_call() returns ZX_OK on success and the number of bytes and count of handles in the reply message are returned via actual_bytes and actual_handles, respectively.

The special return value ZX_ERR_CALL_FAILED indicates that the message was sent, but an error occurred while waiting for a response. This is necessary to disambiguate errors like ZX_ERR_PEER_CLOSED which could have occurred while attempting the write (in which case the caller would still own any handles passed via handles) or while waiting (in which case the caller would no longer own any of the handles). The return parameter read_status is used to indicate the specific error that occurred during the wait or read phase when ZX_ERR_CALL_FAILED is returned.

In the event of ZX_OK, ZX_ERR_TIMED_OUT, or ZX_ERR_CALL_FAILED, the handles in handles have been sent in a message to the other endpoint of the Channel and no longer exist in the calling process. In the event of any other return values, the handles in handles remain in the calling process, unchanged.


ZX_ERR_BAD_HANDLE handle is not a valid handle or any element in handles is not a valid handle.

ZX_ERR_WRONG_TYPE handle is not a channel handle.

ZX_ERR_INVALID_ARGS any of the provided pointers are invalid or null, or there are duplicates among the handles in the handles array, or options is nonzero.

ZX_ERR_ACCESS_DENIED handle does not have ZX_RIGHT_WRITE or any element in handles does not have ZX_RIGHT_TRANSFER.

ZX_ERR_PEER_CLOSED The other side of the channel was closed or became closed while waiting for the reply.

ZX_ERR_CANCELED handle was closed while waiting for a reply.

ZX_ERR_CALL_FAILED The write phase of the call succeeded, but an error occurred while or after waiting for the response. The specific error is returned via read_status if it is non-null.

ZX_ERR_NO_MEMORY (Temporary) Failure due to lack of memory.

ZX_ERR_OUT_OF_RANGE wr_num_bytes or wr_num_handles are larger than the largest allowable size for channel messages.

ZX_ERR_BUFFER_TOO_SMALL rd_num_bytes or rd_num_handles are too small to contain the reply message.

ZX_ERR_NOT_SUPPORTED one of the handles in handles was handle (the handle to the channel being written to).


handle_close, handle_duplicate, handle_replace, object_wait_one, object_wait_many, channel_create, channel_read, channel_write.