crash with gcc and -Os on iOS

SM
s.marek (at) avm.de
Thu, Dec 16, 2010 10:13 AM

Hello,

there's a strange issue with PJSIP 1.8.10 on iOS. XCodes default
optimization level for Release builds is -Os. When compiled this way,
PJSIPs header parser crashes on incoming calls.
When compiling with -O2 or even -O3, everything works fine. XCode uses gcc
4.2 underneath.

I've narrowed it down to a loop that copies header-values into a temporary
header-structure in pjsip_dlg_update_remote_cap().

    while (hdr) {
            unsigned j;
            /* Append the header content to temporary header */
            for(j=0; j<hdr->count &&

tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j)
{
tmp_hdr.values[tmp_hdr.count++] = hdr->values[j];
}

            /* Get the next header for this capability */
            hdr = (const pjsip_generic_array_hdr*)
                    pjsip_msg_find_hdr(msg, htypes[i], hdr->next);
    }

Looks good to me. But shortly after that, some pj_strdup (from
pjsip_hdr_clone) tries to copy those strings from tmp_hdr.values and
there's only garbage in tmp_hdr.values. tmp_hdr.count is fine though.

When I modify the code by adding just a printf below(!!!) the while-loop,
gcc's optimizer is brought back to sanity again and the values are copied
just fine.

    while (hdr) {
            unsigned j;
            /* Append the header content to temporary header */
            for(j=0; j<hdr->count &&

tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j)
{
tmp_hdr.values[tmp_hdr.count++] = hdr->values[j];
}

            /* Get the next header for this capability */
            hdr = (const pjsip_generic_array_hdr*)
                    pjsip_msg_find_hdr(msg, htypes[i], hdr->next);
    }
    printf("[tmp_hdr] %s values (%d)\n", tmp_hdr.name.ptr, 

tmp_hdr.count);

An alterative "fix" was to add a printf on some tmp_hdr value inside the
inner for loop. So in the end I think, gcc gets something wrong by
optimizing access to tmp_hdr too much.

Does anyone know what the real source of the problem might be? What has
Apple done to good old gcc? Or is this even reproducable on a Unix/Linux
platform? Or is it just me?

Thanks in advance for any comment,
Sebastian.

Hello, there's a strange issue with PJSIP 1.8.10 on iOS. XCodes default optimization level for Release builds is -Os. When compiled this way, PJSIPs header parser crashes on incoming calls. When compiling with -O2 or even -O3, everything works fine. XCode uses gcc 4.2 underneath. I've narrowed it down to a loop that copies header-values into a temporary header-structure in pjsip_dlg_update_remote_cap(). while (hdr) { unsigned j; /* Append the header content to temporary header */ for(j=0; j<hdr->count && tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j) { tmp_hdr.values[tmp_hdr.count++] = hdr->values[j]; } /* Get the next header for this capability */ hdr = (const pjsip_generic_array_hdr*) pjsip_msg_find_hdr(msg, htypes[i], hdr->next); } Looks good to me. But shortly after that, some pj_strdup (from pjsip_hdr_clone) tries to copy those strings from tmp_hdr.values and there's only garbage in tmp_hdr.values. tmp_hdr.count is fine though. When I modify the code by adding just a printf below(!!!) the while-loop, gcc's optimizer is brought back to sanity again and the values are copied just fine. while (hdr) { unsigned j; /* Append the header content to temporary header */ for(j=0; j<hdr->count && tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j) { tmp_hdr.values[tmp_hdr.count++] = hdr->values[j]; } /* Get the next header for this capability */ hdr = (const pjsip_generic_array_hdr*) pjsip_msg_find_hdr(msg, htypes[i], hdr->next); } printf("[tmp_hdr] %s values (%d)\n", tmp_hdr.name.ptr, tmp_hdr.count); An alterative "fix" was to add a printf on some tmp_hdr value inside the inner for loop. So in the end I think, gcc gets something wrong by optimizing access to tmp_hdr too much. Does anyone know what the real source of the problem might be? What has Apple done to good old gcc? Or is this even reproducable on a Unix/Linux platform? Or is it just me? Thanks in advance for any comment, Sebastian.
EA
Even André Fiskvik
Thu, Dec 16, 2010 10:42 AM

I'm not sure if it's the same issue as you are having, but we have experienced crashes related to headers as well with the following stacktrace:
Thread 7 Crashed:
0 App 0x00073900 pjsip_contact_hdr_print + 180
1 App 0x00073d64 pjsip_msg_print + 380
2 App 0x0007f298 pjsip_tx_data_encode + 164
3 App 0x0007de98 stateless_send_resolver_callback + 180
4 App 0x0007ee18 srv_resolver_cb + 76
5 App 0x00031a58 dns_callback + 652
6 App 0x0002e114 on_read_complete + 1004
7 App 0x0001ffc4 ioqueue_dispatch_read_event + 396
8 App 0x000211e0 pj_ioqueue_poll + 688
9 App 0x0007b5f8 pjsip_endpt_handle_events2 + 196
10 App 0x00097158 pjsua_handle_events + 60
11 App 0x0009721c worker_thread + 20
12 App 0x000220c4 thread_main + 76
13 libSystem.B.dylib 0x0007a285 _pthread_start + 249

Is you stacktrace looking something similiar?

Best regards,
Even André

On 16. des. 2010, at 11.13, s.marek@avm.de wrote:

Hello,

there's a strange issue with PJSIP 1.8.10 on iOS. XCodes default
optimization level for Release builds is -Os. When compiled this way,
PJSIPs header parser crashes on incoming calls.
When compiling with -O2 or even -O3, everything works fine. XCode uses gcc
4.2 underneath.

I've narrowed it down to a loop that copies header-values into a temporary
header-structure in pjsip_dlg_update_remote_cap().

    while (hdr) {
            unsigned j;
            /* Append the header content to temporary header */
            for(j=0; j<hdr->count &&

tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j)
{
tmp_hdr.values[tmp_hdr.count++] = hdr->values[j];
}

            /* Get the next header for this capability */
            hdr = (const pjsip_generic_array_hdr*)
                    pjsip_msg_find_hdr(msg, htypes[i], hdr->next);
    }

Looks good to me. But shortly after that, some pj_strdup (from
pjsip_hdr_clone) tries to copy those strings from tmp_hdr.values and
there's only garbage in tmp_hdr.values. tmp_hdr.count is fine though.

When I modify the code by adding just a printf below(!!!) the while-loop,
gcc's optimizer is brought back to sanity again and the values are copied
just fine.

    while (hdr) {
            unsigned j;
            /* Append the header content to temporary header */
            for(j=0; j<hdr->count &&

tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j)
{
tmp_hdr.values[tmp_hdr.count++] = hdr->values[j];
}

            /* Get the next header for this capability */
            hdr = (const pjsip_generic_array_hdr*)
                    pjsip_msg_find_hdr(msg, htypes[i], hdr->next);
    }
    printf("[tmp_hdr] %s values (%d)\n", tmp_hdr.name.ptr, 

tmp_hdr.count);

An alterative "fix" was to add a printf on some tmp_hdr value inside the
inner for loop. So in the end I think, gcc gets something wrong by
optimizing access to tmp_hdr too much.

Does anyone know what the real source of the problem might be? What has
Apple done to good old gcc? Or is this even reproducable on a Unix/Linux
platform? Or is it just me?

Thanks in advance for any comment,
Sebastian.


Visit our blog: http://blog.pjsip.org

pjsip mailing list
pjsip@lists.pjsip.org
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org

I'm not sure if it's the same issue as you are having, but we have experienced crashes related to headers as well with the following stacktrace: Thread 7 Crashed: 0 App 0x00073900 pjsip_contact_hdr_print + 180 1 App 0x00073d64 pjsip_msg_print + 380 2 App 0x0007f298 pjsip_tx_data_encode + 164 3 App 0x0007de98 stateless_send_resolver_callback + 180 4 App 0x0007ee18 srv_resolver_cb + 76 5 App 0x00031a58 dns_callback + 652 6 App 0x0002e114 on_read_complete + 1004 7 App 0x0001ffc4 ioqueue_dispatch_read_event + 396 8 App 0x000211e0 pj_ioqueue_poll + 688 9 App 0x0007b5f8 pjsip_endpt_handle_events2 + 196 10 App 0x00097158 pjsua_handle_events + 60 11 App 0x0009721c worker_thread + 20 12 App 0x000220c4 thread_main + 76 13 libSystem.B.dylib 0x0007a285 _pthread_start + 249 Is you stacktrace looking something similiar? Best regards, Even André On 16. des. 2010, at 11.13, s.marek@avm.de wrote: > Hello, > > there's a strange issue with PJSIP 1.8.10 on iOS. XCodes default > optimization level for Release builds is -Os. When compiled this way, > PJSIPs header parser crashes on incoming calls. > When compiling with -O2 or even -O3, everything works fine. XCode uses gcc > 4.2 underneath. > > I've narrowed it down to a loop that copies header-values into a temporary > header-structure in pjsip_dlg_update_remote_cap(). > > while (hdr) { > unsigned j; > /* Append the header content to temporary header */ > for(j=0; j<hdr->count && > tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j) > { > tmp_hdr.values[tmp_hdr.count++] = hdr->values[j]; > } > > /* Get the next header for this capability */ > hdr = (const pjsip_generic_array_hdr*) > pjsip_msg_find_hdr(msg, htypes[i], hdr->next); > } > > Looks good to me. But shortly after that, some pj_strdup (from > pjsip_hdr_clone) tries to copy those strings from tmp_hdr.values and > there's only garbage in tmp_hdr.values. tmp_hdr.count is fine though. > > When I modify the code by adding just a printf below(!!!) the while-loop, > gcc's optimizer is brought back to sanity again and the values are copied > just fine. > > while (hdr) { > unsigned j; > /* Append the header content to temporary header */ > for(j=0; j<hdr->count && > tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j) > { > tmp_hdr.values[tmp_hdr.count++] = hdr->values[j]; > } > > /* Get the next header for this capability */ > hdr = (const pjsip_generic_array_hdr*) > pjsip_msg_find_hdr(msg, htypes[i], hdr->next); > } > printf("[tmp_hdr] %s values (%d)\n", tmp_hdr.name.ptr, > tmp_hdr.count); > > An alterative "fix" was to add a printf on some tmp_hdr value inside the > inner for loop. So in the end I think, gcc gets something wrong by > optimizing access to tmp_hdr too much. > > Does anyone know what the real source of the problem might be? What has > Apple done to good old gcc? Or is this even reproducable on a Unix/Linux > platform? Or is it just me? > > Thanks in advance for any comment, > Sebastian. > > _______________________________________________ > Visit our blog: http://blog.pjsip.org > > pjsip mailing list > pjsip@lists.pjsip.org > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org >
SM
s.marek (at) avm.de
Thu, Dec 16, 2010 11:45 AM

Let's see:

Thread 5 Crashed:
0  libSystem.B.dylib  0x33bde874 longjmp + 8
1  App                0x000676fc pj_throw_exception_ (except.c:54)
2  App                0x00043df6 pool_callback (sip_endpoint.c:134)
3  App                0x0006a950 pj_pool_allocate_find (pool.c:65)
4  App                0x0006a99e pj_pool_alloc (pool_i.h:62)
5  App                0x0006c56a pj_strdup (string_i.h:39)
6  App                0x00044e52 pjsip_generic_array_hdr_clone
(sip_msg.c:938)
7  App                0x00044824 pjsip_hdr_clone (sip_msg.c:569)
8  App                0x0004206a pjsip_dlg_set_remote_cap_hdr
(sip_dialog.c:2159)
9  App                0x00042150 pjsip_dlg_update_remote_cap
(sip_dialog.c:2071)
10  App                0x00043a84 pjsip_dlg_create_uas (sip_dialog.c:529)
11  App                0x0005fe14 pjsua_call_on_incoming
(pjsua_call.c:904)
12  App                0x0006161e mod_pjsua_on_rx_request
(pjsua_core.c:446)
13  App                0x0004410a endpt_on_rx_msg (sip_endpoint.c:903)
14  App                0x0004c5ba pjsip_tpmgr_receive_packet
(sip_transport.c:1512)
15  App                0x0004d1a6 on_data_read (sip_transport_tcp.c:1233)
16  App                0x00066cca ioqueue_on_read_complete
(activesock.c:546)
17  App                0x0006867a ioqueue_dispatch_read_event
(ioqueue_common_abs.c:559)
18  App                0x00068aa6 pj_ioqueue_poll (ioqueue_select.c:902)
19  App                0x00043d48 pjsip_endpt_handle_events2
(sip_endpoint.c:719)
20  App                0x00060698 pjsua_handle_events (pjsua_core.c:1507)
21  App                0x00061648 worker_thread (pjsua_core.c:568)
22  App                0x00069b94 thread_main (os_core_unix.c:494)
23  libSystem.B.dylib  0x33bd6886 _pthread_start + 242
24  libSystem.B.dylib  0x33bcba88 thread_start + 0

Ultimately pj_strdup tries to allocate 4GB of memory, because it takes an
arbitrary memory block as a pj_str_t and what is interpreted as
pj_str_t.slen contains, well, some bytes that result in around 4GB when
read as an unsigned integer. That is a bad idea on an iPhone. ;)

So, I would say our stacktraces look rather different.

Thank you anyway!

Sebastian.

| I'm not sure if it's the same issue as you are having, but we have
| experienced crashes related to headers as well with the following
stacktrace:
| Thread 7 Crashed:
| 0 App 0x00073900 pjsip_contact_hdr_print + 180
| 1 App 0x00073d64 pjsip_msg_print + 380
| 2 App 0x0007f298 pjsip_tx_data_encode + 164
| 3 App 0x0007de98 stateless_send_resolver_callback + 180
| 4 App 0x0007ee18 srv_resolver_cb + 76
| 5 App 0x00031a58 dns_callback + 652
| 6 App 0x0002e114 on_read_complete + 1004
| 7 App 0x0001ffc4 ioqueue_dispatch_read_event + 396
| 8 App 0x000211e0 pj_ioqueue_poll + 688
| 9 App 0x0007b5f8 pjsip_endpt_handle_events2 + 196
| 10 App 0x00097158 pjsua_handle_events + 60
| 11 App 0x0009721c worker_thread + 20
| 12 App 0x000220c4 thread_main + 76
| 13 libSystem.B.dylib 0x0007a285 _pthread_start + 249
|
| Is you stacktrace looking something similiar?
|
| Best regards,
| Even André
|
| On 16. des. 2010, at 11.13, s.marek@avm.de wrote:
|
| Hello,
|
| there's a strange issue with PJSIP 1.8.10 on iOS. XCodes default
| optimization level for Release builds is -Os. When compiled this way,
| PJSIPs header parser crashes on incoming calls.
| When compiling with -O2 or even -O3, everything works fine. XCode uses
gcc
| 4.2 underneath.
|
| I've narrowed it down to a loop that copies header-values into a
temporary
| header-structure in pjsip_dlg_update_remote_cap().
|
|        while (hdr) {
|                unsigned j;
|                /* Append the header content to temporary header /
|                for(j=0; j<hdr->count &&
| tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j)
|                {
|                        tmp_hdr.values[tmp_hdr.count++] = hdr->values[j];
|                }
|
|                /
Get the next header for this capability /
|                hdr = (const pjsip_generic_array_hdr
)
|                        pjsip_msg_find_hdr(msg, htypes[i], hdr->next);
|        }
|
| Looks good to me. But shortly after that, some pj_strdup (from
| pjsip_hdr_clone) tries to copy those strings from tmp_hdr.values and
| there's only garbage in tmp_hdr.values. tmp_hdr.count is fine though.
|
| When I modify the code by adding just a printf below(!!!) the
while-loop,
| gcc's optimizer is brought back to sanity again and the values are
copied
| just fine.
|
|        while (hdr) {
|                unsigned j;
|                /* Append the header content to temporary header /
|                for(j=0; j<hdr->count &&
| tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j)
|                {
|                        tmp_hdr.values[tmp_hdr.count++] = hdr->values[j];
|                }
|
|                /
Get the next header for this capability /
|                hdr = (const pjsip_generic_array_hdr
)
|                        pjsip_msg_find_hdr(msg, htypes[i], hdr->next);
|        }
|        printf("[tmp_hdr] %s values (%d)\n", tmp_hdr.name.ptr,
| tmp_hdr.count);
|
| An alterative "fix" was to add a printf on some tmp_hdr value inside the

| inner for loop. So in the end I think, gcc gets something wrong by
| optimizing access to tmp_hdr too much.
|
| Does anyone know what the real source of the problem might be? What has
| Apple done to good old gcc? Or is this even reproducable on a Unix/Linux

| platform? Or is it just me?
|
| Thanks in advance for any comment,
| Sebastian.
|
| _______________________________________________
| Visit our blog: http://blog.pjsip.org
|
| pjsip mailing list
| pjsip@lists.pjsip.org
| http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org

| _______________________________________________
| Visit our blog: http://blog.pjsip.org
|
| pjsip mailing list
| pjsip@lists.pjsip.org
| http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org

Let's see: Thread 5 Crashed: 0 libSystem.B.dylib 0x33bde874 longjmp + 8 1 App 0x000676fc pj_throw_exception_ (except.c:54) 2 App 0x00043df6 pool_callback (sip_endpoint.c:134) 3 App 0x0006a950 pj_pool_allocate_find (pool.c:65) 4 App 0x0006a99e pj_pool_alloc (pool_i.h:62) 5 App 0x0006c56a pj_strdup (string_i.h:39) 6 App 0x00044e52 pjsip_generic_array_hdr_clone (sip_msg.c:938) 7 App 0x00044824 pjsip_hdr_clone (sip_msg.c:569) 8 App 0x0004206a pjsip_dlg_set_remote_cap_hdr (sip_dialog.c:2159) 9 App 0x00042150 pjsip_dlg_update_remote_cap (sip_dialog.c:2071) 10 App 0x00043a84 pjsip_dlg_create_uas (sip_dialog.c:529) 11 App 0x0005fe14 pjsua_call_on_incoming (pjsua_call.c:904) 12 App 0x0006161e mod_pjsua_on_rx_request (pjsua_core.c:446) 13 App 0x0004410a endpt_on_rx_msg (sip_endpoint.c:903) 14 App 0x0004c5ba pjsip_tpmgr_receive_packet (sip_transport.c:1512) 15 App 0x0004d1a6 on_data_read (sip_transport_tcp.c:1233) 16 App 0x00066cca ioqueue_on_read_complete (activesock.c:546) 17 App 0x0006867a ioqueue_dispatch_read_event (ioqueue_common_abs.c:559) 18 App 0x00068aa6 pj_ioqueue_poll (ioqueue_select.c:902) 19 App 0x00043d48 pjsip_endpt_handle_events2 (sip_endpoint.c:719) 20 App 0x00060698 pjsua_handle_events (pjsua_core.c:1507) 21 App 0x00061648 worker_thread (pjsua_core.c:568) 22 App 0x00069b94 thread_main (os_core_unix.c:494) 23 libSystem.B.dylib 0x33bd6886 _pthread_start + 242 24 libSystem.B.dylib 0x33bcba88 thread_start + 0 Ultimately pj_strdup tries to allocate 4GB of memory, because it takes an arbitrary memory block as a pj_str_t and what is interpreted as pj_str_t.slen contains, well, some bytes that result in around 4GB when read as an unsigned integer. That is a bad idea on an iPhone. ;) So, I would say our stacktraces look rather different. Thank you anyway! Sebastian. | I'm not sure if it's the same issue as you are having, but we have | experienced crashes related to headers as well with the following stacktrace: | Thread 7 Crashed: | 0 App 0x00073900 pjsip_contact_hdr_print + 180 | 1 App 0x00073d64 pjsip_msg_print + 380 | 2 App 0x0007f298 pjsip_tx_data_encode + 164 | 3 App 0x0007de98 stateless_send_resolver_callback + 180 | 4 App 0x0007ee18 srv_resolver_cb + 76 | 5 App 0x00031a58 dns_callback + 652 | 6 App 0x0002e114 on_read_complete + 1004 | 7 App 0x0001ffc4 ioqueue_dispatch_read_event + 396 | 8 App 0x000211e0 pj_ioqueue_poll + 688 | 9 App 0x0007b5f8 pjsip_endpt_handle_events2 + 196 | 10 App 0x00097158 pjsua_handle_events + 60 | 11 App 0x0009721c worker_thread + 20 | 12 App 0x000220c4 thread_main + 76 | 13 libSystem.B.dylib 0x0007a285 _pthread_start + 249 | | Is you stacktrace looking something similiar? | | Best regards, | Even André | | On 16. des. 2010, at 11.13, s.marek@avm.de wrote: | | Hello, | | there's a strange issue with PJSIP 1.8.10 on iOS. XCodes default | optimization level for Release builds is -Os. When compiled this way, | PJSIPs header parser crashes on incoming calls. | When compiling with -O2 or even -O3, everything works fine. XCode uses gcc | 4.2 underneath. | | I've narrowed it down to a loop that copies header-values into a temporary | header-structure in pjsip_dlg_update_remote_cap(). | | while (hdr) { | unsigned j; | /* Append the header content to temporary header */ | for(j=0; j<hdr->count && | tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j) | { | tmp_hdr.values[tmp_hdr.count++] = hdr->values[j]; | } | | /* Get the next header for this capability */ | hdr = (const pjsip_generic_array_hdr*) | pjsip_msg_find_hdr(msg, htypes[i], hdr->next); | } | | Looks good to me. But shortly after that, some pj_strdup (from | pjsip_hdr_clone) tries to copy those strings from tmp_hdr.values and | there's only garbage in tmp_hdr.values. tmp_hdr.count is fine though. | | When I modify the code by adding just a printf below(!!!) the while-loop, | gcc's optimizer is brought back to sanity again and the values are copied | just fine. | | while (hdr) { | unsigned j; | /* Append the header content to temporary header */ | for(j=0; j<hdr->count && | tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j) | { | tmp_hdr.values[tmp_hdr.count++] = hdr->values[j]; | } | | /* Get the next header for this capability */ | hdr = (const pjsip_generic_array_hdr*) | pjsip_msg_find_hdr(msg, htypes[i], hdr->next); | } | printf("[tmp_hdr] %s values (%d)\n", tmp_hdr.name.ptr, | tmp_hdr.count); | | An alterative "fix" was to add a printf on some tmp_hdr value inside the | inner for loop. So in the end I think, gcc gets something wrong by | optimizing access to tmp_hdr too much. | | Does anyone know what the real source of the problem might be? What has | Apple done to good old gcc? Or is this even reproducable on a Unix/Linux | platform? Or is it just me? | | Thanks in advance for any comment, | Sebastian. | | _______________________________________________ | Visit our blog: http://blog.pjsip.org | | pjsip mailing list | pjsip@lists.pjsip.org | http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org | _______________________________________________ | Visit our blog: http://blog.pjsip.org | | pjsip mailing list | pjsip@lists.pjsip.org | http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org
BP
Benny Prijono
Fri, Dec 17, 2010 7:19 AM

That's strange indeed. But we've had problem with certain gcc
optimizations before, https://trac.pjsip.org/repos/ticket/23, and just
as this one we also don't know what's going on.

Can you avoid the problem using a lighter expression than printf? Say,
with PJ_UNUSED_ARG(tmp_hdr.name.ptr).

Best regards,
 Benny

On Thu, Dec 16, 2010 at 5:13 PM,  s.marek@avm.de wrote:

Hello,

there's a strange issue with PJSIP 1.8.10 on iOS. XCodes default
optimization level for Release builds is -Os. When compiled this way,
PJSIPs header parser crashes on incoming calls.
When compiling with -O2 or even -O3, everything works fine. XCode uses gcc
4.2 underneath.

I've narrowed it down to a loop that copies header-values into a temporary
header-structure in pjsip_dlg_update_remote_cap().

       while (hdr) {
               unsigned j;
               /* Append the header content to temporary header */
               for(j=0; j<hdr->count &&
 tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j)
               {
                       tmp_hdr.values[tmp_hdr.count++] = hdr->values[j];
               }

               /* Get the next header for this capability /
               hdr = (const pjsip_generic_array_hdr
)
                       pjsip_msg_find_hdr(msg, htypes[i], hdr->next);
       }

Looks good to me. But shortly after that, some pj_strdup (from
pjsip_hdr_clone) tries to copy those strings from tmp_hdr.values and
there's only garbage in tmp_hdr.values. tmp_hdr.count is fine though.

When I modify the code by adding just a printf below(!!!) the while-loop,
gcc's optimizer is brought back to sanity again and the values are copied
just fine.

       while (hdr) {
               unsigned j;
               /* Append the header content to temporary header */
               for(j=0; j<hdr->count &&
 tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j)
               {
                       tmp_hdr.values[tmp_hdr.count++] = hdr->values[j];
               }

               /* Get the next header for this capability /
               hdr = (const pjsip_generic_array_hdr
)
                       pjsip_msg_find_hdr(msg, htypes[i], hdr->next);
       }
       printf("[tmp_hdr] %s values (%d)\n", tmp_hdr.name.ptr,
tmp_hdr.count);

An alterative "fix" was to add a printf on some tmp_hdr value inside the
inner for loop. So in the end I think, gcc gets something wrong by
optimizing access to tmp_hdr too much.

Does anyone know what the real source of the problem might be? What has
Apple done to good old gcc? Or is this even reproducable on a Unix/Linux
platform? Or is it just me?

Thanks in advance for any comment,
Sebastian.


Visit our blog: http://blog.pjsip.org

pjsip mailing list
pjsip@lists.pjsip.org
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org

That's strange indeed. But we've had problem with certain gcc optimizations before, https://trac.pjsip.org/repos/ticket/23, and just as this one we also don't know what's going on. Can you avoid the problem using a lighter expression than printf? Say, with PJ_UNUSED_ARG(tmp_hdr.name.ptr). Best regards,  Benny On Thu, Dec 16, 2010 at 5:13 PM, <s.marek@avm.de> wrote: > Hello, > > there's a strange issue with PJSIP 1.8.10 on iOS. XCodes default > optimization level for Release builds is -Os. When compiled this way, > PJSIPs header parser crashes on incoming calls. > When compiling with -O2 or even -O3, everything works fine. XCode uses gcc > 4.2 underneath. > > I've narrowed it down to a loop that copies header-values into a temporary > header-structure in pjsip_dlg_update_remote_cap(). > >        while (hdr) { >                unsigned j; >                /* Append the header content to temporary header */ >                for(j=0; j<hdr->count && >  tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j) >                { >                        tmp_hdr.values[tmp_hdr.count++] = hdr->values[j]; >                } > >                /* Get the next header for this capability */ >                hdr = (const pjsip_generic_array_hdr*) >                        pjsip_msg_find_hdr(msg, htypes[i], hdr->next); >        } > > Looks good to me. But shortly after that, some pj_strdup (from > pjsip_hdr_clone) tries to copy those strings from tmp_hdr.values and > there's only garbage in tmp_hdr.values. tmp_hdr.count is fine though. > > When I modify the code by adding just a printf below(!!!) the while-loop, > gcc's optimizer is brought back to sanity again and the values are copied > just fine. > >        while (hdr) { >                unsigned j; >                /* Append the header content to temporary header */ >                for(j=0; j<hdr->count && >  tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j) >                { >                        tmp_hdr.values[tmp_hdr.count++] = hdr->values[j]; >                } > >                /* Get the next header for this capability */ >                hdr = (const pjsip_generic_array_hdr*) >                        pjsip_msg_find_hdr(msg, htypes[i], hdr->next); >        } >        printf("[tmp_hdr] %s values (%d)\n", tmp_hdr.name.ptr, > tmp_hdr.count); > > An alterative "fix" was to add a printf on some tmp_hdr value inside the > inner for loop. So in the end I think, gcc gets something wrong by > optimizing access to tmp_hdr too much. > > Does anyone know what the real source of the problem might be? What has > Apple done to good old gcc? Or is this even reproducable on a Unix/Linux > platform? Or is it just me? > > Thanks in advance for any comment, > Sebastian. > > _______________________________________________ > Visit our blog: http://blog.pjsip.org > > pjsip mailing list > pjsip@lists.pjsip.org > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org >
SM
s.marek (at) avm.de
Fri, Dec 17, 2010 8:59 AM

No, that doesn't fix it. What does, without being too much of a hack, is
dynamically allocating the memory for tmp_hdr, instead of putting it on
the stack.

    pjsip_generic_array_hdr *tmp_hdr = 

malloc(sizeof(pjsip_generic_array_hdr));

    /* Init temporary header */
    pjsip_generic_array_hdr_init(dlg->pool, tmp_hdr, NULL);
    pj_memcpy(tmp_hdr, hdr, sizeof(pjsip_hdr));

    while (hdr) {
            unsigned j;

            /* Append the header content to temporary header */
            for(j=0; j<hdr->count &&
                    tmp_hdr->count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j)
            {
                    tmp_hdr->values[tmp_hdr->count++] = 

hdr->values[j];
}

            /* Get the next header for this capability */
            hdr = (const pjsip_generic_array_hdr*)
                    pjsip_msg_find_hdr(msg, htypes[i], hdr->next);
    }

    /* Save this capability */
    status = pjsip_dlg_set_remote_cap_hdr(dlg, tmp_hdr);
    free(tmp_hdr);
    if (status != PJ_SUCCESS) {
            pjsip_dlg_dec_lock(dlg);
            return status;
    }

Still, seems unnecessary, because that tmp_hdr on the stack looks pretty
ok to me, from an application programmers point of view. Maybe one should
ask the GCC folks, what they think about it?

I would still be interested, if that is related to the Apple GCC version,
or if someone who is building PJSIP on Linux/Unix is able to reproduce
this issue?

Sebastian.

pjsip-bounces@lists.pjsip.org schrieb am 17.12.2010 08:19:07:

| Von: Benny Prijono bennylp@teluu.com
| An: pjsip list pjsip@lists.pjsip.org
| Datum: 17.12.2010 08:19
| Betreff: Re: [pjsip] crash with gcc and -Os on iOS
| Gesendet von: pjsip-bounces@lists.pjsip.org
|
| That's strange indeed. But we've had problem with certain gcc
| optimizations before, https://trac.pjsip.org/repos/ticket/23, and just
| as this one we also don't know what's going on.
|
| Can you avoid the problem using a lighter expression than printf? Say,
| with PJ_UNUSED_ARG(tmp_hdr.name.ptr).
|
| Best regards,
|  Benny
|
|
| On Thu, Dec 16, 2010 at 5:13 PM,  s.marek@avm.de wrote:
| > Hello,
| >
| > there's a strange issue with PJSIP 1.8.10 on iOS. XCodes default
| > optimization level for Release builds is -Os. When compiled this way,
| > PJSIPs header parser crashes on incoming calls.
| > When compiling with -O2 or even -O3, everything works fine. XCode uses
gcc
| > 4.2 underneath.
| >
| > I've narrowed it down to a loop that copies header-values into a
temporary
| > header-structure in pjsip_dlg_update_remote_cap().
| >
| >        while (hdr) {
| >                unsigned j;
| >                /* Append the header content to temporary header /
| >                for(j=0; j<hdr->count &&
| >  tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j)
| >                {
| >                        tmp_hdr.values[tmp_hdr.count++] =
hdr->values[j];
| >                }
| >
| >                /
Get the next header for this capability /
| >                hdr = (const pjsip_generic_array_hdr
)
| >                        pjsip_msg_find_hdr(msg, htypes[i], hdr->next);
| >        }
| >
| > Looks good to me. But shortly after that, some pj_strdup (from
| > pjsip_hdr_clone) tries to copy those strings from tmp_hdr.values and
| > there's only garbage in tmp_hdr.values. tmp_hdr.count is fine though.
| >
| > When I modify the code by adding just a printf below(!!!) the
while-loop,
| > gcc's optimizer is brought back to sanity again and the values are
copied
| > just fine.
| >
| >        while (hdr) {
| >                unsigned j;
| >                /* Append the header content to temporary header /
| >                for(j=0; j<hdr->count &&
| >  tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j)
| >                {
| >                        tmp_hdr.values[tmp_hdr.count++] =
hdr->values[j];
| >                }
| >
| >                /
Get the next header for this capability /
| >                hdr = (const pjsip_generic_array_hdr
)
| >                        pjsip_msg_find_hdr(msg, htypes[i], hdr->next);
| >        }
| >        printf("[tmp_hdr] %s values (%d)\n", tmp_hdr.name.ptr,
| > tmp_hdr.count);
| >
| > An alterative "fix" was to add a printf on some tmp_hdr value inside
the
| > inner for loop. So in the end I think, gcc gets something wrong by
| > optimizing access to tmp_hdr too much.
| >
| > Does anyone know what the real source of the problem might be? What
has
| > Apple done to good old gcc? Or is this even reproducable on a
Unix/Linux
| > platform? Or is it just me?
| >
| > Thanks in advance for any comment,
| > Sebastian.
| >
| > _______________________________________________
| > Visit our blog: http://blog.pjsip.org
| >
| > pjsip mailing list
| > pjsip@lists.pjsip.org
| > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org
| >
|
| _______________________________________________
| Visit our blog: http://blog.pjsip.org
|
| pjsip mailing list
| pjsip@lists.pjsip.org
| http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org

No, that doesn't fix it. What does, without being too much of a hack, is dynamically allocating the memory for tmp_hdr, instead of putting it on the stack. pjsip_generic_array_hdr *tmp_hdr = malloc(sizeof(pjsip_generic_array_hdr)); /* Init temporary header */ pjsip_generic_array_hdr_init(dlg->pool, tmp_hdr, NULL); pj_memcpy(tmp_hdr, hdr, sizeof(pjsip_hdr)); while (hdr) { unsigned j; /* Append the header content to temporary header */ for(j=0; j<hdr->count && tmp_hdr->count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j) { tmp_hdr->values[tmp_hdr->count++] = hdr->values[j]; } /* Get the next header for this capability */ hdr = (const pjsip_generic_array_hdr*) pjsip_msg_find_hdr(msg, htypes[i], hdr->next); } /* Save this capability */ status = pjsip_dlg_set_remote_cap_hdr(dlg, tmp_hdr); free(tmp_hdr); if (status != PJ_SUCCESS) { pjsip_dlg_dec_lock(dlg); return status; } Still, seems unnecessary, because that tmp_hdr on the stack looks pretty ok to me, from an application programmers point of view. Maybe one should ask the GCC folks, what they think about it? I would still be interested, if that is related to the Apple GCC version, or if someone who is building PJSIP on Linux/Unix is able to reproduce this issue? Sebastian. pjsip-bounces@lists.pjsip.org schrieb am 17.12.2010 08:19:07: | Von: Benny Prijono <bennylp@teluu.com> | An: pjsip list <pjsip@lists.pjsip.org> | Datum: 17.12.2010 08:19 | Betreff: Re: [pjsip] crash with gcc and -Os on iOS | Gesendet von: pjsip-bounces@lists.pjsip.org | | That's strange indeed. But we've had problem with certain gcc | optimizations before, https://trac.pjsip.org/repos/ticket/23, and just | as this one we also don't know what's going on. | | Can you avoid the problem using a lighter expression than printf? Say, | with PJ_UNUSED_ARG(tmp_hdr.name.ptr). | | Best regards, | Benny | | | On Thu, Dec 16, 2010 at 5:13 PM, <s.marek@avm.de> wrote: | > Hello, | > | > there's a strange issue with PJSIP 1.8.10 on iOS. XCodes default | > optimization level for Release builds is -Os. When compiled this way, | > PJSIPs header parser crashes on incoming calls. | > When compiling with -O2 or even -O3, everything works fine. XCode uses gcc | > 4.2 underneath. | > | > I've narrowed it down to a loop that copies header-values into a temporary | > header-structure in pjsip_dlg_update_remote_cap(). | > | > while (hdr) { | > unsigned j; | > /* Append the header content to temporary header */ | > for(j=0; j<hdr->count && | > tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j) | > { | > tmp_hdr.values[tmp_hdr.count++] = hdr->values[j]; | > } | > | > /* Get the next header for this capability */ | > hdr = (const pjsip_generic_array_hdr*) | > pjsip_msg_find_hdr(msg, htypes[i], hdr->next); | > } | > | > Looks good to me. But shortly after that, some pj_strdup (from | > pjsip_hdr_clone) tries to copy those strings from tmp_hdr.values and | > there's only garbage in tmp_hdr.values. tmp_hdr.count is fine though. | > | > When I modify the code by adding just a printf below(!!!) the while-loop, | > gcc's optimizer is brought back to sanity again and the values are copied | > just fine. | > | > while (hdr) { | > unsigned j; | > /* Append the header content to temporary header */ | > for(j=0; j<hdr->count && | > tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j) | > { | > tmp_hdr.values[tmp_hdr.count++] = hdr->values[j]; | > } | > | > /* Get the next header for this capability */ | > hdr = (const pjsip_generic_array_hdr*) | > pjsip_msg_find_hdr(msg, htypes[i], hdr->next); | > } | > printf("[tmp_hdr] %s values (%d)\n", tmp_hdr.name.ptr, | > tmp_hdr.count); | > | > An alterative "fix" was to add a printf on some tmp_hdr value inside the | > inner for loop. So in the end I think, gcc gets something wrong by | > optimizing access to tmp_hdr too much. | > | > Does anyone know what the real source of the problem might be? What has | > Apple done to good old gcc? Or is this even reproducable on a Unix/Linux | > platform? Or is it just me? | > | > Thanks in advance for any comment, | > Sebastian. | > | > _______________________________________________ | > Visit our blog: http://blog.pjsip.org | > | > pjsip mailing list | > pjsip@lists.pjsip.org | > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org | > | | _______________________________________________ | Visit our blog: http://blog.pjsip.org | | pjsip mailing list | pjsip@lists.pjsip.org | http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org
BP
Benny Prijono
Fri, Dec 17, 2010 10:19 AM

On Fri, Dec 17, 2010 at 3:59 PM,  s.marek@avm.de wrote:

No, that doesn't fix it.

Okay, PJ_UNUSED_ARG() would probably be optimized out by the compiler
(and that's the objective of PJ_UNUSED_ARG in the first place
actually).

What does, without being too much of a hack, is
dynamically allocating the memory for tmp_hdr, instead of putting it on
the stack.

It's still too "heavy". As you know we don't use malloc, and changing
it to use dlg->pool would add to the memory usage of the dialog.

Can we fool gcc with something like this:

pjsip_generic_array_hdr  tmp_hdr_buf;
pjsip_generic_array_hdr  *tmp_hdr = &tmp_hdr_buf;

Still, seems unnecessary, because that tmp_hdr on the stack looks pretty
ok to me, from an application programmers point of view. Maybe one should
ask the GCC folks, what they think about it?

You can try, but I'unless you can simplify the problem into a simple
compilable program, I would imagine nobody will be interested in
looking into that. Besides, even if this is fixed in newer gcc
version, it will still take months before the fix gets to Apple, and
even then somebody would still face the problem until they upgrade the
compiler.

I would still be interested, if that is related to the Apple GCC version,
or if someone who is building PJSIP on Linux/Unix is able to reproduce
this issue?

It's fine here. gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), x86_64,
-Os, made/received call with pjsua. But I've kind of guessed that.

From past experience, this usually is version/platform specific thing.

Here are two more weird gcc issues in the past:
https://trac.pjsip.org/repos/ticket/766
https://trac.pjsip.org/repos/ticket/683

Thanks
Benny

Sebastian.

On Fri, Dec 17, 2010 at 3:59 PM, <s.marek@avm.de> wrote: > No, that doesn't fix it. Okay, PJ_UNUSED_ARG() would probably be optimized out by the compiler (and that's the objective of PJ_UNUSED_ARG in the first place actually). > What does, without being too much of a hack, is > dynamically allocating the memory for tmp_hdr, instead of putting it on > the stack. > It's still too "heavy". As you know we don't use malloc, and changing it to use dlg->pool would add to the memory usage of the dialog. Can we fool gcc with something like this: pjsip_generic_array_hdr tmp_hdr_buf; pjsip_generic_array_hdr *tmp_hdr = &tmp_hdr_buf; > Still, seems unnecessary, because that tmp_hdr on the stack looks pretty > ok to me, from an application programmers point of view. Maybe one should > ask the GCC folks, what they think about it? > You can try, but I'unless you can simplify the problem into a simple compilable program, I would imagine nobody will be interested in looking into that. Besides, even if this is fixed in newer gcc version, it will still take months before the fix gets to Apple, and even then somebody would still face the problem until they upgrade the compiler. > I would still be interested, if that is related to the Apple GCC version, > or if someone who is building PJSIP on Linux/Unix is able to reproduce > this issue? > It's fine here. gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), x86_64, -Os, made/received call with pjsua. But I've kind of guessed that. >From past experience, this usually is version/platform specific thing. Here are two more weird gcc issues in the past: https://trac.pjsip.org/repos/ticket/766 https://trac.pjsip.org/repos/ticket/683 Thanks Benny > Sebastian. > >