1

for my final project in BScEE i'm trying to create an ad-hoc network. I'm working on Galaxy S2 devices and writing most of my code in C ( JNI ). Except for sending normal message, i'm also automatically sending broadcasts every 5 seconds. There is a thread which is listening and waiting to receive data. I keep crashing due to segmentation fault- using ndk-stack and addr2line it points me to recvfrom : int retval = recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr, &slen); A thought i'm having is that because most of the time there is a thread running and waiting to receive , its a false alarm and the segmentation issue is somewhere else.

How can I debug the cause for the segmentation fault, and if its actually caused by the recvfrom() code. [ I can add here the tombstone if it will help ]

edit 1: fadden the tombstone is 2700 lines long, i added the begining and the end. the end contains our app which directs me to recvfrom.

begining of tombstone:

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'samsung/GT-I9100/GT-I9100:2.3.5/GINGERBREAD/XXKI4:user/release-keys'
pid: 4309, tid: 4309  >>> com.example.adhocktest <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad
r0 00000027  r1 deadbaad  r2 a0000000  r3 00000000
r4 00000001  r5 00000000  r6 00285068  r7 0000a000
r8 00000000  r9 00000014  10 44295df4  fp 802a6374
ip afd466a8  sp bef83210  lr afd196f1  pc afd161c0  cpsr 60000030
d0  4224000043040000  d1  0000002842ba0000
d2  42ba000000000000  d3  0000000000000000
d4  8000000000000000  d5  429800003f800000
d6  00000000c2980000  d7  4110000043040000
d8  3e59364e3d8f5c29  d9  0000002643da8000
d10 0000000042180000  d11 0000000000000000
d12 0000000000000000  d13 0000000000000000
d14 0000000000000000  d15 0000000000000000
d16 c053000000000000  d17 c053000000000000
d18 0000000000000000  d19 0000000000000000
d20 3ff0000000000000  d21 8000000000000000
d22 0000000000000000  d23 0000000000000000
d24 0000000000000000  d25 4071600000000000
d26 4030000000000000  d27 3ff0000000000000
d28 3aa680003a854000  d29 3ff0000000000000
d30 0000000000000000  d31 3ff0000000000000
scr 20000010

     #00  pc 000161c0  /system/lib/libc.so
     #01  pc 00013b30  /system/lib/libc.so
     #02  pc 000149f6  /system/lib/libc.so
     #03  pc 0001a9ea  /system/lib/libutils.so
     #04  pc 0001dc26  /system/lib/libutils.so
     #05  pc 0001dd56  /system/lib/libutils.so
     #06  pc 0001dda2  /system/lib/libutils.so
     #07  pc 000220d8  /system/lib/libutils.so
     #08  pc 00022298  /system/lib/libutils.so
     #09  pc 0005129c  /system/lib/libandroid_runtime.so
     #10  pc 000512a6  /system/lib/libandroid_runtime.so
     #11  pc 00017ef4  /system/lib/libdvm.so
     #12  pc 000498f4  /system/lib/libdvm.so
     #13  pc 0001d108  /system/lib/libdvm.so
     #14  pc 000221a8  /system/lib/libdvm.so
     #15  pc 00021098  /system/lib/libdvm.so
     #16  pc 00060266  /system/lib/libdvm.so
     #17  pc 0006803a  /system/lib/libdvm.so
     #18  pc 0001d108  /system/lib/libdvm.so
     #19  pc 000221a8  /system/lib/libdvm.so
     #20  pc 00021098  /system/lib/libdvm.so
     #21  pc 000600c8  /system/lib/libdvm.so
     #22  pc 0004c3c2  /system/lib/libdvm.so
     #23  pc 0003c316  /system/lib/libandroid_runtime.so
     #24  pc 0003dcaa  /system/lib/libandroid_runtime.so
     #25  pc 00008cca  /system/bin/app_process
     #26  pc 0001506e  /system/lib/libc.so

end of tombstone:

--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
pid: 4309, tid: 4345   Thread-12

r0 fffffe00  r1 002a2bd0  r2 000000c8  r3 00000000
r4 4a0b6b44  r5 4a0b6b30  r6 0000005b  r7 00000124
r8 4a0b6b70  r9 47012fb0  10 47012f98  fp 802a6374
ip 4a0b6b10  sp 4a0b6b00  lr 813027d3  pc afd0c1e4  cpsr 40000010
d0  4140000041a80000  d1  3ff0000041ac0000
d2  4d852dc0424ac9e8  d3  42c8000000540ff0
d4  bf800000002a9e00  d5  0000000000000000
d6  3f80000000000000  d7  4030000000000000
d8  0000000000000000  d9  0000000000000000
d10 0000000000000000  d11 0000000000000000
d12 0000000000000000  d13 0000000000000000
d14 0000000000000000  d15 0000000000000000
d16 000000000005f007  d17 0000800000008000
d18 ffd4cb1affd52334  d19 ffa54dd2ffa604a4
d20 ffffa7e6ffffa7e6  d21 ffff492effff492e
d22 0001c5a20001c5a2  d23 000166e9000166e9
d24 0000000200000002  d25 0000000000000000
d26 0000000000000000  d27 0000000000000000
d28 0000000000000000  d29 0000000000000000
d30 0000000000000000  d31 0000000000000000
scr 20000010

     #00  pc 0000c1e4  /system/lib/libc.so
     #01  pc 000027d0  /data/data/com.example.adhocktest/lib/libadhoc-jni.so
     #02  pc 00017ef4  /system/lib/libdvm.so
     #03  pc 000498f4  /system/lib/libdvm.so
     #04  pc 0001d108  /system/lib/libdvm.so
     #05  pc 000221a8  /system/lib/libdvm.so
     #06  pc 00021098  /system/lib/libdvm.so
     #07  pc 000600c8  /system/lib/libdvm.so
     #08  pc 000602dc  /system/lib/libdvm.so
     #09  pc 0005462a  /system/lib/libdvm.so
     #10  pc 00011e00  /system/lib/libc.so
     #11  pc 000119cc  /system/lib/libc.so

This is the receive JNI function :

jstring
Java_com_example_adhocktest_ReceiverUDP_RecvUdpJNI(JNIEnv* env1,
    jobject thiz)
    {
int PORT = 8888;
int BUFLEN = 10240;
int retVal=-1;
int is_ignore_msg = 0;
int is_forward_msg = 0;

__android_log_write(ANDROID_LOG_INFO, "RecvUdpJNI()",  "Entering RecvUdpJNI"); // TODO: Remove

struct sockaddr_in my_addr, cli_addr;
int sockfd, i;
socklen_t slen=sizeof(cli_addr);
char* buf;
char* strstrptr;
buf = (char*)malloc(BUFLEN*sizeof(char));
if (buf == NULL) {
    __android_log_print(ANDROID_LOG_INFO, "NetworkMap","RecvUdpJNI(): failed. could not allocate memory for buf");
}

if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) {
    free(buf);
    return (*env1)->NewStringUTF(env1, "socket");
}


bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(sockfd, (struct sockaddr* ) &my_addr, sizeof(my_addr))==-1) {
    free(buf);
    return (*env1)->NewStringUTF(env1, "bind");
}

__android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): Gonna try to receive"); // TODO: Delete
//try to receive
int retval = recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr, &slen); // retval equals the number of bytes(chars) received
__android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): Done receive retval=[%d]",retval);// TODO: Delete
if (retval==-1) {
    return (*env1)->NewStringUTF(env1, "errRecv");
}
__android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): BUF BEFORE=[%s]",buf);// TODO: Delete
buf[retval] = '\0';
__android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): BUF AFTER=[%s]",buf);// TODO: Delete

char* target_ip;
char* next_hop_ip;

if (strcmp(inet_ntoa(cli_addr.sin_addr),MyNetworkMap->node_base_ip)==0) {                                   // MSG is an echo from myself
    __android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): Ignoring echo from myself");
} else {                                                                                            // MSG is not from myself, analyze
    if (IsHelloMsg(buf) == TRUE) {
        if (IsNodeForbidden(inet_ntoa(cli_addr.sin_addr)) == 1){
            __android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): Ignoring HELLO_MSG from  [%s]", inet_ntoa(cli_addr.sin_addr));
        }
        else{
            __android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): Going to process hello");// TODO: Delete
            ProcessHelloMsg(strpbrk(buf,":")+1,strlen(strpbrk(buf,":")+1),MyNetworkMap);
        }
    } else {
        __android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): Entering ExtractTargetFromHeader [%s]", buf); // TODO: Delete
        char* target_ip = ExtractTargetFromHeader(buf);
        char* next_hop_ip = ExtractNextHopFromHeader(buf);


        if (strcmp(inet_ntoa(cli_addr.sin_addr),MyNetworkMap->node_base_ip)==0) { // Message received is an echo from myself.
            __android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): IGNORE_MSG [%s]", buf);
            is_ignore_msg = 1;
        } else {

            if (strcmp(MyNetworkMap->node_base_ip,target_ip)==0) {
                __android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): I AM THE TARGET OF THE MSG [%s]", buf);
            } else if (strcmp(next_hop_ip,MyNetworkMap->node_base_ip)==0) {
                __android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): I AM THE NEXT HOP OF THE MSG [%s]", buf);
                is_forward_msg = 1;
            } else {        // NOTE : For the moment we do not need messages that we are not the next hop or target of.
                            //          In the future we may want to keep this side information for opportunistic decoding.
                __android_log_print(ANDROID_LOG_INFO, "WARNING","RecvUdpJNI(): I am neither the source,target or nexthop of this message [%s]", buf);
                is_ignore_msg = 1;
            }
        }
    }
}

__android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): Raw string: <%s>",buf);
//if received successfully , close socket
__android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): Received");
close(sockfd);

char* return_str = (char*)malloc(sizeof(char)*200);
if (is_ignore_msg == 1) {
    sprintf(return_str, "ignoring message [%s]",buf);
    free(buf);
    return (*env1)->NewStringUTF(env1, "ignore"); // return ignore
} else {

    if (network_coding_on == TRUE) {
        //decrypt
        __android_log_print(ANDROID_LOG_INFO, "WARNING",  "RecvUdpJNI(): Network coding decryption not yet fully implemented");
        SourceList* source_list = GetSourceFromString(buf);
        // continue decryption
    }

    if (is_forward_msg == 1) {
        //forward message
        __android_log_print(ANDROID_LOG_INFO, "WARNING",  "RecvUdpJNI(): Old next hop code for forwarding");
        strstrptr = strstr(buf,";")+1;
        __android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c",  "RecvUdpJNI(): target_ip extracted before calling SendUdpJNI: <%s>",target_ip);
        SendUdpJNI(target_ip,PORT,strstrptr,1,0,strlen(strstrptr)); // TODO: When we add XOR we have to use the message length integer instead of strlen()
        sprintf(return_str, "forwarding message [%s]",buf);
        free(buf);
        return (*env1)->NewStringUTF(env1, return_str);
    } else { // I AM THE TARGET OF THE MESSAGE
        //read message
        strstrptr = strstr(buf,";");
        if (strstrptr != NULL) {
            return (*env1)->NewStringUTF(env1, strstrptr+1); // only return the MSG part
        } else {
            return (*env1)->NewStringUTF(env1, buf); // TODO: this should be an error
        }
    }
}

}

Thanks to whoever can save me here :(

  • Well, 'buf[retval] = '\0';' sounds good if the rx data is guaranteed to not contain any nulls. Unfortunately, you try to use a '[%s] format specifier on the line before to log 'buf'. TRIPLE CHECK all 'str*' style calls to ensure that they always operate on a C-style null-terminated string. – Martin James Apr 28 '14 at 15:07
  • Failure to understand the C-style null-terminated 'strings', (yes, they are pretty hopeless as a string type), seem to be the #1 reason for problems in network code. Misuse of the str*() calls in network code has achieved legendary status and I always look for them before anything else in 'my network program segfaults' questions. – Martin James Apr 28 '14 at 15:12
  • The weird thing is that our code is sending "hello msg's" every 5 secs for a long time without crashing. the VERY moment we send a manual message, the recvfrom of the sending device crashes with seg.fault. as to the log right after recvfrom __android_log_print(ANDROID_LOG_INFO, "adhoc-jni.c", "RecvUdpJNI(): Done receive retval=[%d]",retval); we do not even get to this point, the recvfrom itself crashes. We dont work with pthreads, only threads started by java. Could you recommend a way to debug this? Thanks for the help. – user2968541 Apr 28 '14 at 15:18
  • For best results, show the top part of the native crash (address, register dump, stack frame) in the question. I'd also recommend adding a log message before the recvfrom() call that prints the values of every argument. – fadden Apr 28 '14 at 19:14
  • fadden, what do you think should make me suspect when checking the values before recvfrom() .. ? I added a portion of the tombstone also to the post.. thanks – user2968541 Apr 29 '14 at 16:32

0 Answers0