[pjsip] What about python?

Benny Prijono bennylp at pjsip.org
Wed May 21 06:23:21 EDT 2008


On Wed, May 21, 2008 at 7:07 AM, Turnaev Eugeny <turnaev at t72.ru> wrote:
>
> Suppose situation:
>
> I have an active call and valid call_id,
> now i want to connect or disconnect port from conference.
> So i have to call for example:
>
> status = py_pjsua.conf_connect(player_port, call_port)
>
> How can i check in python that player_port, call_port and call port are valid?
>
> Well seems easy...
> call_port = py_pjsua.call_get_conf_port(call_id)
> player_port = py_pjsua.player_get_conf_port(player_id)
>
> if call_port >= 0 and player_port >= 0:
>        do stuff.. ports are valid
>
> Now imagine:
>
>
> if call_port >= 0 and player_port >= 0:
>
>        # here context switch ! .. callback is called
>        # and call becomes invalid .. and also
>        # call_port becomes invalid..
>        # context switch back to this function
>
>        status = py_pjsua.conf_connect(player_port, call_port)
>
>        # a call to py_pjsua.conf_connect(player_port, call_port)
>        # will fail and application will  suddenly exit!
>
>
>
> #                               py_pjsua.c
>
> static PyObject *py_pjsua_conf_connect
> (PyObject *pSelf, PyObject *pArgs)
> {
>    ...
>
>    status = pjsua_conf_connect(source, sink);
>
>    return Py_BuildValue("i", status);
> }
>
>
>
> #                               pjsua_media.c
>
> PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source,
>                                        pjsua_conf_port_id sink)
> {
>    return pjmedia_conf_connect_port(pjsua_var.mconf, source, sink, 0);
> }
>
>
>
> #                               conference.c
>
> PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf,
>                                               unsigned src_slot,
>                                               unsigned sink_slot,
>                                               int level )
> {
>        ....
>    /* Check arguments */
>    PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports &&
>                     sink_slot<conf->max_ports, PJ_EINVAL);
>
>    /* Ports must be valid. */
>    PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL);
>    PJ_ASSERT_RETURN(conf->ports[sink_slot] != NULL, PJ_EINVAL);
>
>
>
>
> as i understand.. this macro will return from function PJ_EINVAL
> and PJ_EINVAL and then must be returned from python envelope
> as return Py_BuildValue("i", status);
>
> but i see in console:
>
>  11:43:59.968 os_core_unix.c pjlib 0.8.0-trunk for POSIX initialized
>  11:43:59.969 sip_endpoint.c Creating endpoint instance...
>  11:43:59.969          pjlib select() I/O Queue created (0xb7799098)
>  11:43:59.969 sip_endpoint.c Module "mod-msg-print" registered
>  11:43:59.969 sip_transport. Transport manager created.
> python: ../src/pjmedia/conference.c:914: pjmedia_conf_connect_port: Assertion `conf && src_slot<conf->max_ports && sink_slot<conf->max_ports' failed.
> Aborted
>
>
> and application exits..
>
> How i can workaround this ?
>
> I think the correct way would be to return status
>        status = py_pjsua.conf_connect(player_port, call_port)
> from conf_connect call as invalid status..
> or at least raise an exception in py_pjsua.c -> static PyObject *py_pjsua_conf_connect function.
>
> Also this problem mirrors in
> conf_disconnect and i suspect many other python envelopes.
> (For example call_id .. i can retrieve call_id with enum_calls in python.. then a context may be switched.. call become invalid
>  context switch back and i would call something that PJ_ASSERT_RETURN( call_id is valid ) -> that would crash my python app too
>  i guess )
>

How about building the libraries with CFLAGS+=-DNDEBUG? ;-)

We have a pretty strong convention about the use of assert vs the
usual error handling throughout the libraries. Assertion is used to
trap developer's mistake (developer can be you or me) and it must not
be used as a replacement for error handling. And assertion must not be
used for errors coming from external events, such as incoming message
from remote party; in this case, only error handling must be used.

PJ_ASSERT_RETURN does both. The idea is to trap programming error
during development phase (with assert), and once the application is
built in release mode, we can safely turn assertion off (with
-DNDEBUG) and it will switch its behavior to use error handling
instead.

So because of this you can safely turn assertion off in your release
build (Windows apps do that all the time, and that's what I always do
too). Or you can turn if off during development too if this is too
annoying for you. :)

Cheers
 Benny




More information about the pjsip mailing list