Managing errors in IDL

It is not recommended to use out arguments in an IDL description to return codes of logical errors occurring when a request is handled by the server entity to the client entity. Instead, it is recommended to use error arguments.

A logical error is an error that occurs when the server entity is handling a request and must be returned to the client entity. For example, if a client entity attempts to open a non-existent file, the file system server returns a logical error. Internal errors of the server entity such as memory shortage or invalid statement execution are not logical errors.

Use of error arguments enables the following:

The IDL language and NK compiler provide two ways to use error arguments:

The types and macros for handling errors are provided in the file named /opt/KasperskyOS-Community-Edition-<version>/toolchain/include/nk/types.h

Simplified error handling

When employing simplified error handling, the methods of interfaces can have no more than one error argument of the UInt16 type named status.

In case of an error:

If the request is successfully handled:

For example, let's examine an IDL description of an interface containing one method:

Connection.idl

typedef UInt16 ErrorCode

// error code example

const ErrorCode ESendFailed = 10;

interface {

Send(in Handle handle,

in Packet packet,

out UInt32 sentLen,

// the Send method has one UInt16-type error argument named status

error ErrorCode status

);

}

Implementation of the server entity:

server.c

...

// Send method implementation

nk_err_t Send_impl(struct Connection *self,

const struct Connection_Send_req *req,

const struct nk_arena* req_arena,

struct Connection_Send_res* res,

struct nk_arena* res_arena)

{

if (...) {

// if the request is successfully handled, put the result into an out argument and return NK_EOK

res->sentLen = value;

return NK_EOK;

} else {

// if an error occurs, return the result of the NK_ELOGIC_MAKE macro

return NK_ELOGIC_MAKE(Connection_ESendFailed);

}

Implementation of the client entity:

client.c

// the values of the returned error argument of the method are packaged into a result code of the corresponding client interface method

nk_err_t ret = Connection_Send(ctx,

&req, &req_arena,

&res, NK_NULL);

if (ret == NK_EOK) {

// if there are no errors, res contains the values of out arguments

return res.sentLen;

} else {

if (NK_ELOGIC_CHECK(ret)) {

// handle the logical error

} else {

// handle the transport error

}

}

Extended error handling

When employing extended error handling, the methods of interfaces can have more than one error argument of any type.

In case of an error:

If the request is successfully handled:

For example, let's examine an IDL description of an interface containing one method:

Connection.idl

typedef UInt16 ErrorCode

interface {

Send(in Handle handle,

in Packet packet,

out UInt32 sentLen,

// the Send method has one UInt16-type error argument named status

error ErrorCode status

);

}

The union type generated by the NK compiler for the constant part of a response message for this method contains out arguments and error arguments:

Connection.idl.h

...

struct Connection_Send_res {

union {

struct {

struct nk_message base_;

nk_uint32_t sentLen;

};

struct {

struct nk_message base_;

nk_uint32_t sentLen;

} res_;

struct kl_Connection_Send_err {

struct nk_message base_;

nk_uint16_t status

} err_;

};

};

...

Implementation of the server entity:

server.c

...

// Send method implementation

nk_err_t Send_impl(struct Connection *self,

const struct Connection_Send_req *req,

const struct nk_arena* req_arena,

struct Connection_Send_res* res,

struct nk_arena* res_arena)

{

if (...) {

// if the request is successfully handled, put the result into an out argument and return NK_EOK

res->sentLen = value;

return NK_EOK;

} else {

// if an error occurs, call the nk_err_reset() macro to set the error flag in the response message

nk_err_reset(res)

// complete the fields of err arguments in the res->err_ structure

res->err_.status = 10;

// return NK_EOK

return NK_EOK;

}

Implementation of the client entity:

client.c

nk_err_t ret = Connection_Send(ctx,

&req, &req_arena,

&res, NK_NULL);

if (ret == NK_EOK) {

if (nk_msg_check_err(res)) {

// handle the logical error

// the values of returned error arguments of a method are provided in the internal fields of the response message structure

return res.err_.status;

} else {

// if there are no errors, res contains the values of out arguments

return res.sentLen;

}

} else {

// handle the transport error

}

Page top