Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segmentation Fault on Ubuntu 14.10 / gcc 4.9.1 #395

Closed
jblackaby opened this issue Jan 9, 2015 · 9 comments
Closed

Segmentation Fault on Ubuntu 14.10 / gcc 4.9.1 #395

jblackaby opened this issue Jan 9, 2015 · 9 comments

Comments

@jblackaby
Copy link

Hi,

I have been using websocketpp successfully on several Mac OS and Linux systems (great library by the way). I recently moved to Ubuntu 14.10 with gcc 4.9.1 and I am now having an issue. It seems that if the client (web browser, Chrome or Firefox) sends a message that is 32 bytes or longer to the server (C++ app, websocket++), it crashes the server with a segfault. This only happens when using the -O3 compiler flag, otherwise it works correctly.

I have come up with a minimal test which reproduces it:

websockettest.cpp:

#include <iostream>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>

using namespace std;

websocketpp::server<websocketpp::config::asio> server;

void on_open(websocketpp::connection_hdl hdl)
{
    cout << "connected." << endl;
}

void on_close(websocketpp::connection_hdl hdl)
{
    cout << "disconnected." << endl;
}

void on_message(websocketpp::connection_hdl hdl,
                             websocketpp::server<websocketpp::config::asio>::message_ptr msg)
{
    if(msg->get_opcode() == websocketpp::frame::opcode::text) {
        cout << "received message: " << endl <<  msg->get_payload() << endl;
    }   
}

int main()
{
    int port = 9002;
    server.set_access_channels(websocketpp::log::alevel::all);
    server.set_reuse_addr(true);
    server.init_asio();
    server.set_message_handler(bind(&on_message, websocketpp::lib::placeholders::_1, websocketpp::lib::placeholders::_2));
    server.set_open_handler(bind(&on_open, websocketpp::lib::placeholders::_1));
    server.set_close_handler(bind(&on_close, websocketpp::lib::placeholders::_1));
    cout << "starting server on port: " << port << endl;
    server.listen(port);
    server.start_accept();
    server.run();
    return 0;
}

websockettest.html:

<!DOCTYPE html>
<html>
    <meta charset="utf-8" />
    <head>
    <script language="javascript" type="text/javascript">
        var ws_uri = "ws://localhost:9002";
        var socket;
        function init() 
        {
            socket = new WebSocket(ws_uri);
            socket.onopen = on_open;
            socket.onclose = on_close;
            socket.onmessage = on_message;
        }

        function on_open(evt)
        {
            console.log('CONNECTED');
            socket.send('0123456789012345678901234567890');
            socket.send('01234567890123456789012345678901');
        }
        function on_close(evt) { console.log('DISCONNECTED'); }
        function on_message(evt) { console.log('got message'); }

        window.onload = init;
    </script>
</html>

On every other system and when not using the -O3 compiler flag, this works and the server prints:

connected.
received message: 
0123456789012345678901234567890
received message:
01234567890123456789012345678901

On Ubuntu 14.10/GCC 4.9.1 I get:

connected.
received message: 
0123456789012345678901234567890
Segmentation fault (core dumped)

The segfault occurs before the on_message handler is fired. I could not debug it effectively with gdb since the problem only occurs with the -O3 flag, but by just using printfs, I was able to narrow it down to the word_mask_circ() function in frame.hpp. It seemed like all of the arguments were valid so I can not figure out what the problem is. I have tried 0.4.0 and the development branch.

@zaphoyd
Copy link
Owner

zaphoyd commented Jan 10, 2015

can you try defining WEBSOCKETPP_STRICT_MASKING in the preprocessor and let me know if that fixes it?

@jblackaby
Copy link
Author

Yes, that seems to have fixed it.

@zaphoyd
Copy link
Owner

zaphoyd commented Jan 10, 2015

By default WebSocket++ uses a masking system that bends the normal aliasing rules a bit for a sizable speed boost. Certain more exotic CPUs and very aggressive optimization flags are confused by this. That define forces strict masking that is slower but fully standard.

@kallaballa
Copy link

i encountered the exact same problem with debian 7 on armv7l (BananaPi) with g++-4.9.2-10.

@Calthron
Copy link

Calthron commented Oct 8, 2015

Can a static_assert or some other method be used in code to catch this during development?

@TyRoXx
Copy link

TyRoXx commented Oct 9, 2015

Websocket++ does not "bend" the rules. It violates them which leads to undefined behavior in this function:

inline void word_mask_exact(uint8_t* input, uint8_t* output, size_t length,
    const masking_key_type& key)
{
    size_t prepared_key = prepare_masking_key(key);
    size_t n = length/sizeof(size_t);
    size_t* input_word = reinterpret_cast<size_t*>(input);
    size_t* output_word = reinterpret_cast<size_t*>(output);

    for (size_t i = 0; i < n; i++) {
        output_word[i] = input_word[i] ^ prepared_key; // this line
    }

    for (size_t i = n*sizeof(size_t); i < length; i++) {
        output[i] = input[i] ^ key.c[i%4];
    }
}

The compiler may assume that any pointer to a size_t is properly aligned for a size_t. This is probably not the case for either the input or the output pointer.

ARM is not exotic and "aggressive" optimization flags are the norm. It is not the compiler who is confused by this issue.

@zaphoyd
Copy link
Owner

zaphoyd commented Oct 13, 2015

Looking in more detail at the exact rules for portability with respect to aliasing I agree with @TyRoXx. This sort of optimization can only be done safely with platform specific SIMD systems. I will be changing the default masking code to use the slower but well defined byte based masking.

@LocutusOfBorg
Copy link
Contributor

thanks for fixing it! Please make a new release with the fix :)
(also because I would like to upload the new version in Debian, where 0.6.0 is the last release)

mkm85 pushed a commit to mkm85/websocketpp that referenced this issue Feb 14, 2016
@zaphoyd
Copy link
Owner

zaphoyd commented Feb 22, 2016

This fix has been committed and released in 0.7.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants