Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Segmentation fault from a function that is not called at all

Ok, this is really freaking me out. I have a following function that just reads input and returns a string

unsigned char* readFromIn() {
    unsigned char* text = malloc(1024);
    if (fgets(text, 1024, stdin) != NULL) {          <--This is what's causing segmentation fault
        int textLen = strlen(text);
        if (textLen > 0 && text[textLen - 1] == '\n')
            text[textLen - 1] = '\0';     // getting rid of newline character
        return text;
    }
    else {
        free(text);
        return NULL;
    }
}

The thing is, this function isn't called anywhere and just to confirm, I changed the name of the function to something crazy like 9rawiohawr90awrhiokawrioawr and put printf statement on the top of the function.

I'm genuinely not sure why an uncalled function might cause a segmentation fault error.

I'm using gcc 4.6.3 on ubuntu.

Edit: I know that the line

if (fgets(text, 1024, stdin) != NULL) { 

is the offending code because as soon as i comment out that conditional, no segmentation error occurs.

I know that the function is NOT being called because i'm seeing no output of the printf debug statement I put.

Edit2: I've tried changing the type from unsigned char to char. Still segmentation error. I will try to get gdb output.

Edit3: gdb backtrace produced the following

#0 0xb7fa5ac2 in _IO_2_1_stdin_ () from /lib/i386-linux-gnu/libc.so.6
#1 0xb7faf2fb in libwebsocket_create_context (info=0xbffff280) at libwebsockets.c:2125
#2 0x0804a5bb in main()

doing frame 0,1,2 doesn't output anything interesting in particular.

Edit4: I've tried all of the suggestions in the comment, but to no avail, I still get the same segmentation fault.

So I installed a fresh copy of Ubuntu on a virtual OS and recompiled my code. Still the same issue occurs. It seems to me the problem is in either some obscurity going on in my code or the library itself. I've created a minimal example demonstrating the problem:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libwebsockets.h>


unsigned char* readFromIn() {
    unsigned char* text = malloc(1024);
    if (fgets(text, 1024, stdin) != NULL) { <--SEGMENTATION FAULT HERE
        int textLen = strlen(text);
        if (textLen > 0 && text[textLen - 1] == '\n')
            text[textLen - 1] = '\0';    
        return text;
    }
    else {
        free(text);
        return NULL;
    }
}

int callback_http(struct libwebsocket_context *context,
                         struct libwebsocket *wsi,
                         enum libwebsocket_callback_reasons reason, void *user,
                         void *in, size_t len)
{
    return 0;
}

static struct libwebsocket_protocols protocols[] = {
    /* first protocol must always be HTTP handler */
    {
        "http-only",   // name
        callback_http, // callback
        0              // per_session_data_size
    }
};

int main(void) {
    printf("Initializing Web Server\n");
        // server url will be http://localhost:8081
    int port = 8081;
    const char *interface = NULL;
    struct libwebsocket_context *context;
    // we're not using ssl
    const char *cert_path = NULL;
    const char *key_path = NULL;
    // no special options
    int opts = 0;


    struct lws_context_creation_info info;

    memset(&info, 0, sizeof info);
    info.port = port;
    info.iface = interface;
    info.protocols = protocols;
    info.extensions = libwebsocket_get_internal_extensions();
    info.ssl_cert_filepath = NULL;
    info.ssl_private_key_filepath = NULL;
    info.gid = -1;
    info.uid = -1;
    info.options = opts;

    context = libwebsocket_create_context(&info);
    if (context == NULL) {
        fprintf(stderr, "libwebsocket init failed\n");
        return 0;
    }

    printf("starting server...\n");

    while (1) {
        libwebsocket_service(context, 50);
    }
    printf("Shutting server down...\n");
    libwebsocket_context_destroy(context);

    return 0;
}

And here's how I compiled my code

gcc -g testbug.c -o test -lwebsockets

Here's the library I'm using

http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/tag/?id=v1.23-chrome32-firefox24

You will see that I'm not calling the function readFromIn() yet, segmentation fault occurs as soon as you try to run the executable.

I've re-ran gdb and this time, backtrace and the frames tell me a little bit more info.

(gdb) run
Starting program: /home/l46kok/Desktop/websocketserver/test 
Initializing Web Server
[1384002761:2270] NOTICE: Initial logging level 7
[1384002761:2270] NOTICE: Library version: 1.3 unknown-build-hash
[1384002761:2271] NOTICE:  Started with daemon pid 0
[1384002761:2271] NOTICE:  static allocation: 4448 + (12 x 1024 fds) = 16736 bytes
[1384002761:2271] NOTICE:  canonical_hostname = ubuntu
[1384002761:2271] NOTICE:  Compiled with OpenSSL support
[1384002761:2271] NOTICE:  Using non-SSL mode
[1384002761:2271] NOTICE:  per-conn mem: 124 + 1360 headers + protocol rx buf
[1384002761:2294] NOTICE:  Listening on port 8081

Program received signal SIGSEGV, Segmentation fault.
0xb7fb1ac0 in _IO_2_1_stdin_ () from /lib/i386-linux-gnu/libc.so.6
(gdb) backtrace
#0  0xb7fb1ac0 in _IO_2_1_stdin_ () from /lib/i386-linux-gnu/libc.so.6
#1  0xb7fcc2c6 in libwebsocket_create_context () from /usr/local/lib/libwebsockets.so.4.0.0
#2  0x080488c4 in main () at testbug.c:483
(gdb) frame 1
#1  0xb7fcc2c6 in libwebsocket_create_context () from /usr/local/lib/libwebsockets.so.4.0.0
(gdb) frame 2
#2  0x080488c4 in main () at testbug.c:483
483         context = libwebsocket_create_context(&info);

So yeah.. I think I gave all the information at hand.. but I'm genuinely not sure what the issue is. The program causes segmentation fault at line 483 but the issue is gone when I comment out the offending function that's not being called.

like image 315
l46kok Avatar asked Nov 07 '13 08:11

l46kok


People also ask

How do I find out what is causing my segmentation fault?

Check shell limits Usually it is the limit on stack size that causes this kind of problem. To check memory limits, use the ulimit command in bash or ksh , or the limit command in csh or tcsh . Try setting the stacksize higher, and then re-run your program to see if the segfault goes away.

How can I fix segmentation fault?

It can be resolved by having a base condition to return from the recursive function. A pointer must point to valid memory before accessing it.

What does segmentation fault 11 mean in C?

1) Segmentation Fault (also known as SIGSEGV and is usually signal 11) occur when the program tries to write/read outside the memory allocated for it or when writing memory which can only be read.In other words when the program tries to access the memory to which it doesn't have access to.

What kind of error is this segmentation fault?

A common run-time error for C programs by beginners is a "segmentation violation" or "segmentation fault." When you run your program and the system reports a "segmentation violation," it means your program has attempted to access an area of memory that it is not allowed to access.


1 Answers

Probably you're missing something when initializing libwebsockets.

Indeed, recompiling libwebsockets with debug reveals that:

GNU gdb (GDB) 7.6.1 (Debian 7.6.1-1)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/vili/x...done.
(gdb) r
Starting program: /home/vili/./x
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?
Initializing Web Server
[1384020141:5692] NOTICE: Initial logging level 7
[1384020141:5692] NOTICE: Library version: 1.2
[1384020141:5693] NOTICE:  Started with daemon pid 0
[1384020141:5693] NOTICE:  static allocation: 5512 + (16 x 1024 fds) = 21896 bytes
[1384020141:5693] NOTICE:  canonical_hostname = x220
[1384020141:5693] NOTICE:  Compiled with OpenSSL support
[1384020141:5693] NOTICE:  Using non-SSL mode
[1384020141:5693] NOTICE:  per-conn mem: 248 + 1328 headers + protocol rx buf
[1384020141:5713] NOTICE:  Listening on port 8081

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bc2080 in _IO_2_1_stderr_ () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0  0x00007ffff7bc2080 in _IO_2_1_stderr_ () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007ffff7bcd83c in libwebsocket_create_context (info=0x7fffffffe580)
    at libwebsockets.c:2093
#2  0x0000000000400918 in main () at x.c:66
(gdb) up
#1  0x00007ffff7bcd83c in libwebsocket_create_context (info=0x7fffffffe580)
    at libwebsockets.c:2093
2093                    info->protocols[context->count_protocols].callback(context,
(gdb) p context->count_protocols
$1 = 1
(gdb) p info->protocols[1]
$2 = {
  name = 0x7ffff7bc2240 <_IO_2_1_stdin_> "\210 \255", <incomplete sequence \373>, callback = 0x7ffff7bc2080 <_IO_2_1_stderr_>,
  per_session_data_size = 140737349689696, rx_buffer_size = 0,
  owning_server = 0x602010, protocol_index = 1}
(gdb)

Quite likely you need to close the array of libwebsocket_protocols with a special entry (NULL) so that the lib will know how many entries it got via info->protocols.

Edit: yep, check the docs: http://jsk.pp.ua/knowledge/libwebsocket.html

Array of structures listing supported protocols and a protocol- specific callback for each one. The list is ended with an entry that has a NULL callback pointer.

like image 112
ldx Avatar answered Sep 25 '22 10:09

ldx