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

Add support for progressive call results #9

Closed
estan opened this issue Aug 29, 2015 · 49 comments · Fixed by #34
Closed

Add support for progressive call results #9

estan opened this issue Aug 29, 2015 · 49 comments · Fixed by #34
Labels

Comments

@estan
Copy link

estan commented Aug 29, 2015

Great to finally see this in the light David (and all you others of course)! It looks great.

We're currently using Crossbar at work, but treating it as a "black box" and not making use of its application component hosting features (and many other features), and using another router which is more slim is thus of interest to us.

One thing we need though from the Advanced Profile is progressive call result (a stable part), as we're using this to deliver frames from an image detector. I don't know how high up on your agenda this is, but I'm filing this issue to keep track.

@davidchappelle
Copy link
Collaborator

Thank you for your support and interest. Progressive call results is a key feature and is fairly high on my list. I suspect that it is at most a fews days of coding and testing to add to bonefish. I should have some spare time over the next few weeks to make it happen.

@estan
Copy link
Author

estan commented Aug 29, 2015

\o/

@davidchappelle
Copy link
Collaborator

Looks like I will have time on Saturday to start looking into this.

@davidchappelle davidchappelle changed the title [feature] Add support for progressive call results Add support for progressive call results Nov 5, 2015
@jpetso
Copy link
Contributor

jpetso commented Nov 5, 2015

We're going to hold you to that, Dave! My recommendation is underpromise & overdeliver :)

@davidchappelle
Copy link
Collaborator

I got this work started on Sat. I should be able to wrap it up next weekend.

@jpetso
Copy link
Contributor

jpetso commented Jan 7, 2016

Dave, if this requires more work still, can you push your (presumably unfinished) code to your branch so potentially interested parties could take it from there?

@davidchappelle
Copy link
Collaborator

Sure thing. At some point tomorrow I should be able to push what I have.

On Thu, Jan 7, 2016 at 5:35 PM, Jakob Petsovits notifications@github.com
wrote:

Dave, if this requires more work still, can you push your (presumably
unfinished) code to your branch so potentially interested parties could
take it from there?


Reply to this email directly or view it on GitHub
#9 (comment).

@pramukta
Copy link

pramukta commented Jan 8, 2016

Awesome, thanks.

@davidchappelle
Copy link
Collaborator

Still working on it. Just need a bit of time over the weekend to finish
things up.

On Fri, Jan 8, 2016 at 12:50 PM, Pramukta Kumar notifications@github.com
wrote:

Awesome, thanks.


Reply to this email directly or view it on GitHub
#9 (comment).

@davidchappelle
Copy link
Collaborator

@pramukta @estan I have pushed a patch to https://github.com/davidchappelle/bonefish.git for progressive call result support. Once you clone that repo just checkout the feature/progressive_call_results branch.

I haven't had a chance to do much in terms of testing as I am on the road now until 11:30pm. I have a corresponding autobahn-cpp commit in progress as well and should have that in tomorrow. If someone wants to test things out with autobahn-python in the meantime that would be great.

@estan
Copy link
Author

estan commented Jan 9, 2016

This is embarrassing, but I'm actually having trouble checking out the branch. It's not visible in git branch -r after a git clone --recursive:

[estan@pyret bonefish]$ git remote -v
origin  https://github.com/tplgy/bonefish.git (fetch)
origin  https://github.com/tplgy/bonefish.git (push)
[estan@pyret bonefish]$ git fetch origin
[estan@pyret bonefish]$ git branch -r
  origin/HEAD -> origin/master
  origin/master
[estan@pyret bonefish]$

Anyone know what the problem might be? The branch is clearly visible in GitHub UI.

@jrogers
Copy link
Contributor

jrogers commented Jan 9, 2016

@estan, probably because it's in Dave's own fork :) you could add his repot as a remote.

@estan
Copy link
Author

estan commented Jan 9, 2016

@jrogers facepalm. Thanks :)

@estan
Copy link
Author

estan commented Jan 9, 2016

@davidchappelle, I may be wrong, but shouldn't

https://github.com/davidchappelle/bonefish/blob/master/src/bonefish/messages/wamp_result_message.hpp#L166

be ==, not != ? I hit that assert while testing. Right now having another problem I'm trying to debug.

@davidchappelle
Copy link
Collaborator

Yes you are correct.

On Saturday, January 9, 2016, Elvis Stansvik notifications@github.com
wrote:

@davidchappelle https://github.com/davidchappelle, I may be wrong, but
shouldn't

https://github.com/davidchappelle/bonefish/blob/master/src/bonefish/messages/wamp_result_message.hpp#L166

be ==, not != ? I hit that assert while testing. Right now having another
problem I'm trying to debug.


Reply to this email directly or view it on GitHub
#9 (comment).

@estan
Copy link
Author

estan commented Jan 9, 2016

Alright, if I change that to ==, I instead hit this assert in rapidjson when the router tries to serialize the RESULT (I think):

[estan@pyret bonefish-build]$ gdb ./daemon/bonefish
GNU gdb (GDB) 7.10.1
Copyright (C) 2015 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-unknown-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./daemon/bonefish...done.
(gdb) run  --realm "crossbardemo" --websocket-port 8080
Starting program: /home/estan/Nedladdat/bonefish-build/daemon/bonefish --realm "crossbardemo" --websocket-port 8080
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
bonefish: /home/estan/Nedladdat/bonefish/third-party/rapidjson/include/rapidjson/writer.h:328: void rapidjson::Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator>::Prefix(rapidjson::Type) [with OutputStream = bonefish::{anonymous}::omemstream; SourceEncoding = rapidjson::UTF8<>; TargetEncoding = rapidjson::UTF8<>; StackAllocator = rapidjson::CrtAllocator]: Assertion `type == kStringType' failed.

Program received signal SIGABRT, Aborted.
0x00007ffff6db35f8 in raise () from /usr/lib/libc.so.6
(gdb) bt
#0  0x00007ffff6db35f8 in raise () from /usr/lib/libc.so.6
#1  0x00007ffff6db4a7a in abort () from /usr/lib/libc.so.6
#2  0x00007ffff6dac417 in __assert_fail_base () from /usr/lib/libc.so.6
#3  0x00007ffff6dac4c2 in __assert_fail () from /usr/lib/libc.so.6
#4  0x00000000007ba6fa in rapidjson::Writer<bonefish::(anonymous namespace)::omemstream, rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator>::Prefix (this=0x7fffffffbb10, 
    type=rapidjson::kNullType) at /home/estan/Nedladdat/bonefish/third-party/rapidjson/include/rapidjson/writer.h:328
#5  0x00000000007bade1 in rapidjson::Writer<bonefish::(anonymous namespace)::omemstream, rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator>::Null (this=0x7fffffffbb10)
    at /home/estan/Nedladdat/bonefish/third-party/rapidjson/include/rapidjson/writer.h:108
#6  0x00000000007bac49 in json_msgpack::write_json<rapidjson::Writer<bonefish::(anonymous namespace)::omemstream>, json_msgpack::no_custom_string_conversion> (writer=..., o=...)
    at /home/estan/Nedladdat/bonefish/third-party/json-msgpack/include/json_msgpack/json_msgpack_sax.hpp:338
#7  0x00000000007ba2f8 in json_msgpack::write_json<rapidjson::Writer<bonefish::(anonymous namespace)::omemstream>, bonefish::(anonymous namespace)::wamp_bin_string_conversion> (writer=..., 
    o=...) at /home/estan/Nedladdat/bonefish/third-party/json-msgpack/include/json_msgpack/json_msgpack_sax.hpp:327
#8  0x00000000007b9e03 in bonefish::json_serializer::serialize (this=0xb9e5d0, message=...) at /home/estan/Nedladdat/bonefish/src/bonefish/serialization/json_serializer.cpp:214
#9  0x000000000082ff1b in bonefish::websocket_transport::send_message(bonefish::wamp_message&&) (this=0xba6e30, 
    message=<unknown type in /home/estan/Nedladdat/bonefish-build/daemon/bonefish, CU 0x38bafc, DIE 0x3cd406>)
    at /home/estan/Nedladdat/bonefish/src/bonefish/websocket/websocket_transport.cpp:40
#10 0x000000000084eee9 in bonefish::wamp_dealer::process_yield_message (this=0xb9fa50, session_id=..., yield_message=0xbaeb90)
    at /home/estan/Nedladdat/bonefish/src/bonefish/dealer/wamp_dealer.cpp:478
#11 0x00000000007b10e2 in bonefish::wamp_router_impl::process_yield_message (this=0xb9ef40, session_id=..., yield_message=0xbaeb90)
    at /home/estan/Nedladdat/bonefish/src/bonefish/router/wamp_router_impl.cpp:273
#12 0x00000000007a94b2 in bonefish::wamp_router::process_yield_message (this=0xb9e500, session_id=..., yield_message=0xbaeb90)
    at /home/estan/Nedladdat/bonefish/src/bonefish/router/wamp_router.cpp:138
#13 0x00000000008452b5 in bonefish::wamp_message_processor::process_message(std::unique_ptr<bonefish::wamp_message, std::default_delete<bonefish::wamp_message> > const&, std::unique_ptr<bonefish::wamp_transport, std::default_delete<bonefish::wamp_transport> >&&, bonefish::wamp_connection_base*) (this=0xba0918, message=std::unique_ptr<bonefish::wamp_message> containing 0xbaeb90, 
    transport=<unknown type in /home/estan/Nedladdat/bonefish-build/daemon/bonefish, CU 0x459219, DIE 0x495841>, connection=0xba0ef0)
    at /home/estan/Nedladdat/bonefish/src/bonefish/common/wamp_message_processor.cpp:165
#14 0x00000000007d0fd4 in bonefish::websocket_server_impl::on_message (this=0xba08d0, handle=std::weak_ptr (count 6, weak 8) 0xba0ef0, buffer=std::shared_ptr (count 3, weak 0) 0xbae530)
    at /home/estan/Nedladdat/bonefish/src/bonefish/websocket/websocket_server_impl.cpp:218
#15 0x00000000007cfd46 in bonefish::websocket_server_impl::<lambda(websocketpp::connection_hdl, websocketpp::endpoint<websocketpp::connection<bonefish::websocket_config>, bonefish::websocket_config>::message_ptr)>::operator()(websocketpp::connection_hdl, websocketpp::endpoint<websocketpp::connection<bonefish::websocket_config>, bonefish::websocket_config>::message_ptr) const (
    __closure=0xba6330, handle=std::weak_ptr (count 6, weak 8) 0xba0ef0, message=std::shared_ptr (count 3, weak 0) 0xbae530)
    at /home/estan/Nedladdat/bonefish/src/bonefish/websocket/websocket_server_impl.cpp:108
#16 0x00000000007d1dc0 in std::_Function_handler<void(std::weak_ptr<void>, std::shared_ptr<websocketpp::message_buffer::message<websocketpp::message_buffer::alloc::con_msg_manager> >), bonefish::websocket_server_impl::start(const boost::asio::ip::address&, uint16_t)::<lambda(websocketpp::connection_hdl, websocketpp::endpoint<websocketpp::connection<bonefish::websocket_config>, bonefish::websocket_config>::message_ptr)> >::_M_invoke(const std::_Any_data &, <unknown type in /home/estan/Nedladdat/bonefish-build/daemon/bonefish, CU 0x295a52, DIE 0x330949>, <unknown type in /home/estan/Nedladdat/bonefish-build/daemon/bonefish, CU 0x295a52, DIE 0x33094e>) (__functor=..., 
    __args#0=<unknown type in /home/estan/Nedladdat/bonefish-build/daemon/bonefish, CU 0x295a52, DIE 0x330949>, 
    __args#1=<unknown type in /home/estan/Nedladdat/bonefish-build/daemon/bonefish, CU 0x295a52, DIE 0x33094e>) at /usr/include/c++/5.3.0/functional:1871
#17 0x0000000000806485 in std::function<void (std::weak_ptr<void>, std::shared_ptr<websocketpp::message_buffer::message<websocketpp::message_buffer::alloc::con_msg_manager> >)>::operator()(std::weak_ptr<void>, std::shared_ptr<websocketpp::message_buffer::message<websocketpp::message_buffer::alloc::con_msg_manager> >) const (this=0xba1a90, __args#0=std::weak_ptr (empty) 0x0, 
    __args#1=std::shared_ptr (empty) 0x0) at /usr/include/c++/5.3.0/functional:2271
---Type <return> to continue, or q <return> to quit---

Haven't quite figured out what happens.

I'm testing right now with the examples/twisted/wamp/rpc/progress from AutobahnPython.

@estan
Copy link
Author

estan commented Jan 9, 2016

The debug output from bonefish when running frontend.py and getting this crash is:

[2016-01-09 22:22:13] [connect] WebSocket Connection 127.0.0.1:47436 v13 "AutobahnPython/0.11.0" / 101
[wamp_message_processor.cpp:46][process_message] processing message: hello
[wamp_router_impl.cpp:108][attach_session] attaching session: session [2257228500326156,crossbardemo,none]
[wamp_dealer.cpp:65][attach_session] attach session: session [2257228500326156,crossbardemo,none]
[wamp_broker.cpp:51][attach_session] attach session: session [2257228500326156,crossbardemo,none]
[wamp_router_impl.cpp:164][process_hello_message] session [2257228500326156,crossbardemo,none], hello [crossbardemo, {"roles":{"subscriber":{"features":{"publisher_identification":true, "pattern_based_subscription":true, "subscription_revocation":true}}, "publisher":{"features":{"publisher_identification":true, "publisher_exclusion":true, "subscriber_blackwhite_listing":true}}, "caller":{"features":{"caller_identification":true, "progressive_call_results":true}}, "callee":{"features":{"progressive_call_results":true, "pattern_based_registration":true, "registration_revocation":true, "shared_registration":true, "caller_identification":true}}}}]
[wamp_router_impl.cpp:192][process_hello_message] session [2257228500326156,crossbardemo,open], welcome [2257228500326156, {"roles":{"dealer":{"features":{"call_timeout":true, "progressive_call_results":true}}, "broker":{}}}]
[websocket_transport.cpp:39][send_message] sending message: welcome
[2016-01-09 22:22:13] [frame_header] Dispatching write containing 1 message(s) containing 2 header bytes and 120 payload bytes
[2016-01-09 22:22:13] [frame_header] Header Bytes: 
[0] (2) 81 78 

[2016-01-09 22:22:13] [frame_payload] Payload Bytes: 
[0] (120) [1] [2,2257228500326156,{"roles":{"dealer":{"features":{"call_timeout":true,"progressive_call_results":true}},"broker":{}}}]

[wamp_message_processor.cpp:46][process_message] processing message: call
[wamp_dealer.cpp:166][process_call_message] session [2257228500326156,crossbardemo,open], call [1, {"receive_progress":true}, com.myapp.longop, [3], nil]
[wamp_dealer.cpp:219][process_call_message] session [2257228500326156,crossbardemo,open], invocation [1, 1, {"receive_progress":true}, [3], nil]
[websocket_transport.cpp:39][send_message] sending message: invocation
[2016-01-09 22:22:13] [frame_header] Dispatching write containing 1 message(s) containing 2 header bytes and 38 payload bytes
[2016-01-09 22:22:13] [frame_header] Header Bytes: 
[0] (2) 81 26 

[2016-01-09 22:22:13] [frame_payload] Payload Bytes: 
[0] (38) [1] [68,1,1,{"receive_progress":true},[3]]

[wamp_message_processor.cpp:46][process_message] processing message: yield
[wamp_dealer.cpp:424][process_yield_message] session [7090515283965860,crossbardemo,open], yield [1, {"progress":true}, [0], nil]
[wamp_dealer.cpp:477][process_yield_message] session [7090515283965860,crossbardemo,open], result [1, {nil:nil}, [0], nil]
[websocket_transport.cpp:39][send_message] sending message: result
bonefish: /home/estan/Nedladdat/bonefish/third-party/rapidjson/include/rapidjson/writer.h:328: void rapidjson::Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator>::Prefix(rapidjson::Type) [with OutputStream = bonefish::{anonymous}::omemstream; SourceEncoding = rapidjson::UTF8<>; TargetEncoding = rapidjson::UTF8<>; StackAllocator = rapidjson::CrtAllocator]: Assertion `type == kStringType' failed.
Aborted (core dumped)
[estan@pyret bonefish-build]$

@davidchappelle
Copy link
Collaborator

The result object doesn't look right.

On Saturday, January 9, 2016, Elvis Stansvik notifications@github.com
wrote:

The debug output from bonefish when running frontend.py and getting this
crash is:

[2016-01-09 22:22:13] [connect] WebSocket Connection 127.0.0.1:47436 v13 "AutobahnPython/0.11.0" / 101
[wamp_message_processor.cpp:46][process_message] processing message: hello
[wamp_router_impl.cpp:108][attach_session] attaching session: session [2257228500326156,crossbardemo,none]
[wamp_dealer.cpp:65][attach_session] attach session: session [2257228500326156,crossbardemo,none]
[wamp_broker.cpp:51][attach_session] attach session: session [2257228500326156,crossbardemo,none]
[wamp_router_impl.cpp:164][process_hello_message] session [2257228500326156,crossbardemo,none], hello [crossbardemo, {"roles":{"subscriber":{"features":{"publisher_identification":true, "pattern_based_subscription":true, "subscription_revocation":true}}, "publisher":{"features":{"publisher_identification":true, "publisher_exclusion":true, "subscriber_blackwhite_listing":true}}, "caller":{"features":{"caller_identification":true, "progressive_call_results":true}}, "callee":{"features":{"progressive_call_results":true, "pattern_based_registration":true, "registration_revocation":true, "shared_registration":true, "caller_identification":true}}}}]
[wamp_router_impl.cpp:192][process_hello_message] session [2257228500326156,crossbardemo,open], welcome [2257228500326156, {"roles":{"dealer":{"features":{"call_timeout":true, "progressive_call_results":true}}, "broker":{}}}]
[websocket_transport.cpp:39][send_message] sending message: welcome
[2016-01-09 22:22:13] [frame_header] Dispatching write containing 1 message(s) containing 2 header bytes and 120 payload bytes
[2016-01-09 22:22:13] [frame_header] Header Bytes:
0 81 78

[2016-01-09 22:22:13] [frame_payload] Payload Bytes:
0 [1] [2,2257228500326156,{"roles":{"dealer":{"features":{"call_timeout":true,"progressive_call_results":true}},"broker":{}}}]

[wamp_message_processor.cpp:46][process_message] processing message: call
[wamp_dealer.cpp:166][process_call_message] session [2257228500326156,crossbardemo,open], call [1, {"receive_progress":true}, com.myapp.longop, [3], nil]
[wamp_dealer.cpp:219][process_call_message] session [2257228500326156,crossbardemo,open], invocation [1, 1, {"receive_progress":true}, [3], nil]
[websocket_transport.cpp:39][send_message] sending message: invocation
[2016-01-09 22:22:13] [frame_header] Dispatching write containing 1 message(s) containing 2 header bytes and 38 payload bytes
[2016-01-09 22:22:13] [frame_header] Header Bytes:
0 81 26

[2016-01-09 22:22:13] [frame_payload] Payload Bytes:
0 [1] [68,1,1,{"receive_progress":true},[3]]

[wamp_message_processor.cpp:46][process_message] processing message: yield
[wamp_dealer.cpp:424][process_yield_message] session [7090515283965860,crossbardemo,open], yield [1, {"progress":true}, [0], nil]
[wamp_dealer.cpp:477][process_yield_message] session [7090515283965860,crossbardemo,open], result [1, {nil:nil}, [0], nil]
[websocket_transport.cpp:39][send_message] sending message: result
bonefish: /home/estan/Nedladdat/bonefish/third-party/rapidjson/include/rapidjson/writer.h:328: void rapidjson::Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator>::Prefix(rapidjson::Type) [with OutputStream = bonefish::{anonymous}::omemstream; SourceEncoding = rapidjson::UTF8<>; TargetEncoding = rapidjson::UTF8<>; StackAllocator = rapidjson::CrtAllocator]: Assertion `type == kStringType' failed.
Aborted (core dumped)
[estan@pyret bonefish-build]$


Reply to this email directly or view it on GitHub
#9 (comment).

@davidchappelle
Copy link
Collaborator

Looks like the result details are invalid. Maybe not getting set correctly.

On Saturday, January 9, 2016, Elvis Stansvik notifications@github.com
wrote:

The debug output from bonefish when running frontend.py and getting this
crash is:

[2016-01-09 22:22:13] [connect] WebSocket Connection 127.0.0.1:47436 v13 "AutobahnPython/0.11.0" / 101
[wamp_message_processor.cpp:46][process_message] processing message: hello
[wamp_router_impl.cpp:108][attach_session] attaching session: session [2257228500326156,crossbardemo,none]
[wamp_dealer.cpp:65][attach_session] attach session: session [2257228500326156,crossbardemo,none]
[wamp_broker.cpp:51][attach_session] attach session: session [2257228500326156,crossbardemo,none]
[wamp_router_impl.cpp:164][process_hello_message] session [2257228500326156,crossbardemo,none], hello [crossbardemo, {"roles":{"subscriber":{"features":{"publisher_identification":true, "pattern_based_subscription":true, "subscription_revocation":true}}, "publisher":{"features":{"publisher_identification":true, "publisher_exclusion":true, "subscriber_blackwhite_listing":true}}, "caller":{"features":{"caller_identification":true, "progressive_call_results":true}}, "callee":{"features":{"progressive_call_results":true, "pattern_based_registration":true, "registration_revocation":true, "shared_registration":true, "caller_identification":true}}}}]
[wamp_router_impl.cpp:192][process_hello_message] session [2257228500326156,crossbardemo,open], welcome [2257228500326156, {"roles":{"dealer":{"features":{"call_timeout":true, "progressive_call_results":true}}, "broker":{}}}]
[websocket_transport.cpp:39][send_message] sending message: welcome
[2016-01-09 22:22:13] [frame_header] Dispatching write containing 1 message(s) containing 2 header bytes and 120 payload bytes
[2016-01-09 22:22:13] [frame_header] Header Bytes:
0 81 78

[2016-01-09 22:22:13] [frame_payload] Payload Bytes:
0 [1] [2,2257228500326156,{"roles":{"dealer":{"features":{"call_timeout":true,"progressive_call_results":true}},"broker":{}}}]

[wamp_message_processor.cpp:46][process_message] processing message: call
[wamp_dealer.cpp:166][process_call_message] session [2257228500326156,crossbardemo,open], call [1, {"receive_progress":true}, com.myapp.longop, [3], nil]
[wamp_dealer.cpp:219][process_call_message] session [2257228500326156,crossbardemo,open], invocation [1, 1, {"receive_progress":true}, [3], nil]
[websocket_transport.cpp:39][send_message] sending message: invocation
[2016-01-09 22:22:13] [frame_header] Dispatching write containing 1 message(s) containing 2 header bytes and 38 payload bytes
[2016-01-09 22:22:13] [frame_header] Header Bytes:
0 81 26

[2016-01-09 22:22:13] [frame_payload] Payload Bytes:
0 [1] [68,1,1,{"receive_progress":true},[3]]

[wamp_message_processor.cpp:46][process_message] processing message: yield
[wamp_dealer.cpp:424][process_yield_message] session [7090515283965860,crossbardemo,open], yield [1, {"progress":true}, [0], nil]
[wamp_dealer.cpp:477][process_yield_message] session [7090515283965860,crossbardemo,open], result [1, {nil:nil}, [0], nil]
[websocket_transport.cpp:39][send_message] sending message: result
bonefish: /home/estan/Nedladdat/bonefish/third-party/rapidjson/include/rapidjson/writer.h:328: void rapidjson::Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator>::Prefix(rapidjson::Type) [with OutputStream = bonefish::{anonymous}::omemstream; SourceEncoding = rapidjson::UTF8<>; TargetEncoding = rapidjson::UTF8<>; StackAllocator = rapidjson::CrtAllocator]: Assertion `type == kStringType' failed.
Aborted (core dumped)
[estan@pyret bonefish-build]$


Reply to this email directly or view it on GitHub
#9 (comment).

@estan
Copy link
Author

estan commented Jan 9, 2016

I haven't used msgpack before, but this:

 result_message->set_details(result_details.marshal(yield_message->get_zone()));

Shouldn't that be result_message->get_zone()?

@estan
Copy link
Author

estan commented Jan 9, 2016

If I change that, it seems to get a little further in processing the YIELDs:

[wamp_message_processor.cpp:46][process_message] processing message: yield
[wamp_dealer.cpp:424][process_yield_message] session [7090515283965860,crossbardemo,open], yield [1, {"progress":true}, [0], nil]
[wamp_dealer.cpp:477][process_yield_message] session [7090515283965860,crossbardemo,open], result [1, {"progress":true}, [0], nil]
[websocket_transport.cpp:39][send_message] sending message: result
[2016-01-09 22:34:33] [frame_header] Dispatching write containing 1 message(s) containing 2 header bytes and 28 payload bytes
[2016-01-09 22:34:33] [frame_header] Header Bytes: 
[0] (2) 81 1C 

[2016-01-09 22:34:33] [frame_payload] Payload Bytes: 
[0] (28) [1] [50,1,{"progress":true},[0]]

[wamp_message_processor.cpp:46][process_message] processing message: yield
[wamp_dealer.cpp:424][process_yield_message] session [7090515283965860,crossbardemo,open], yield [1, {"progress":true}, [1], nil]
[wamp_dealer.cpp:428][process_yield_message] unable to find invocation ... timed out or session closed
[wamp_message_processor.cpp:46][process_message] processing message: yield
[wamp_dealer.cpp:424][process_yield_message] session [7090515283965860,crossbardemo,open], yield [1, {"progress":true}, [2], nil]
[wamp_dealer.cpp:428][process_yield_message] unable to find invocation ... timed out or session closed
[wamp_message_processor.cpp:46][process_message] processing message: yield
[wamp_dealer.cpp:424][process_yield_message] session [7090515283965860,crossbardemo,open], yield [1, {}, [3], nil]
[wamp_dealer.cpp:428][process_yield_message] unable to find invocation ... timed out or session closed

@davidchappelle
Copy link
Collaborator

Yep good catch. Apologies for the bugs. Time crunch this morning getting
out the door.

On Saturday, January 9, 2016, Elvis Stansvik notifications@github.com
wrote:

I haven't used msgpack before, but this:

result_message->set_details(result_details.marshal(yield_message->get_zone()));

Shouldn't that be result_message->get_zone()?


Reply to this email directly or view it on GitHub
#9 (comment).

@estan
Copy link
Author

estan commented Jan 9, 2016

That is, it seems it's able to send the first RESULT to the caller:

(test_env)[estan@pyret progress]$ python frontend.py
2016-01-09T22:34:33+0100 Starting factory <autobahn.twisted.websocket.WampWebSocketClientFactory object at 0x7faf44b55710>
2016-01-09T22:34:33+0100 session attached
2016-01-09T22:34:33+0100 Progress: 0

But after that, the invocation seems gone in the router.

@estan
Copy link
Author

estan commented Jan 9, 2016

Heh, no problem :)

@estan
Copy link
Author

estan commented Jan 9, 2016

I guess it's the unconditional erasure of the invocation at the end of wamp_dealer::process_yield_message that's the culprit. I think it will need some more logic to keep the invocation alive for the duration of the call?

@estan
Copy link
Author

estan commented Jan 9, 2016

Anyway, I gotto go to bed, but this looks promising. Thanks!

@estan
Copy link
Author

estan commented Jan 9, 2016

I just had to quickly test, and with

diff --git a/src/bonefish/dealer/wamp_dealer.cpp b/src/bonefish/dealer/wamp_dealer.cpp
index ecd67c6..1a179a0 100644
--- a/src/bonefish/dealer/wamp_dealer.cpp
+++ b/src/bonefish/dealer/wamp_dealer.cpp
@@ -466,7 +466,7 @@ void wamp_dealer::process_yield_message(const wamp_session_id& session_id,
     std::unique_ptr<wamp_result_message> result_message(
             new wamp_result_message(std::move(yield_message->release_zone())));
     result_message->set_request_id(dealer_invocation->get_request_id());
-    result_message->set_details(result_details.marshal(yield_message->get_zone()));
+    result_message->set_details(result_details.marshal(result_message->get_zone()));
     result_message->set_arguments(yield_message->get_arguments());
     result_message->set_arguments_kw(yield_message->get_arguments_kw());

@@ -483,9 +483,11 @@ void wamp_dealer::process_yield_message(const wamp_session_id& session_id,
     // will detach the session. When this happens the pending invocations
     // be cleaned up. So we don't use an iterator here to erase the pending
     // invocation because it may have just been invalidated above.
-    m_pending_callee_invocations[session_id].erase(request_id);
-    m_pending_caller_invocations[session->get_session_id()].erase(request_id);
-    m_pending_invocations.erase(request_id);
+    if (!yield_options.get_option_or("progress", false)) {
+        m_pending_callee_invocations[session_id].erase(request_id);
+        m_pending_caller_invocations[session->get_session_id()].erase(request_id);
+        m_pending_invocations.erase(request_id);
+    }
 }

 void wamp_dealer::send_error(const std::unique_ptr<wamp_transport>& transport,
diff --git a/src/bonefish/messages/wamp_result_message.hpp b/src/bonefish/messages/wamp_result_message.hpp
index 3ec1af1..802a591 100644
--- a/src/bonefish/messages/wamp_result_message.hpp
+++ b/src/bonefish/messages/wamp_result_message.hpp
@@ -163,7 +163,7 @@ inline void wamp_result_message::set_request_id(const wamp_request_id& request_i

 inline void wamp_result_message::set_details(const msgpack::object& details)
 {
-    if (details.type != msgpack::type::MAP) {
+    if (details.type == msgpack::type::MAP) {
         m_details = msgpack::object(details, get_zone());
     } else {
         throw std::invalid_argument("invalid details");

it seems to work:

(test_env)[estan@pyret progress]$ python frontend.py
2016-01-09T23:13:32+0100 Starting factory <autobahn.twisted.websocket.WampWebSocketClientFactory object at 0x7f0667c3b710>
2016-01-09T23:13:32+0100 session attached
2016-01-09T23:13:32+0100 Progress: 0
2016-01-09T23:13:33+0100 Progress: 1
2016-01-09T23:13:34+0100 Progress: 2
2016-01-09T23:13:35+0100 Final: 3
2016-01-09T23:13:35+0100 wamp.error.goodbye_and_out: None
2016-01-09T23:13:35+0100 disconnected
2016-01-09T23:13:35+0100 Stopping factory <autobahn.twisted.websocket.WampWebSocketClientFactory object at 0x7f0667c3b710>
2016-01-09T23:13:35+0100 Main loop terminated.
(test_env)[estan@pyret progress]$

But I have no idea if the if (!yield_options.get_option_or("progress", false)) I added is a too liberal/crude fix :P

@estan
Copy link
Author

estan commented Jan 10, 2016

@davidchappelle, I'm a little unsure on how important the order of things in process_yield_message is, but those .erase that are done in the middle of the method, is it important that those are kept there, before the sending of the result message? The invocations will be removed anyway at the end of the function AFAICS.

If it's not important that they are removed there and then, then I think the function could be simplified a little with:

diff --git a/src/bonefish/dealer/wamp_dealer.cpp b/src/bonefish/dealer/wamp_dealer.cpp
index ecd67c6..c86a9e7 100644
--- a/src/bonefish/dealer/wamp_dealer.cpp
+++ b/src/bonefish/dealer/wamp_dealer.cpp
@@ -435,11 +435,12 @@ void wamp_dealer::process_yield_message(const wamp_session_id& session_id,
     // We can't have a pending invocation without a pending caller/callee
     // as they are tracked in a synchronized manner. So to have one without
     // the other is considered to be an error.
-    auto pending_callee_invocations_itr =
-            m_pending_callee_invocations.find(session_itr->second->get_session_id());
-    if (pending_callee_invocations_itr == m_pending_callee_invocations.end()) {
+    if (!m_pending_callee_invocations.count(session_itr->second->get_session_id())) {
         throw std::logic_error("dealer pending callee invocations out of sync");
     }
+    if (!m_pending_caller_invocations.count(session->get_session_id())) {
+        throw std::logic_error("dealer pending caller invocations out of sync");
+    }

     wamp_yield_options yield_options;
     yield_options.unmarshal(yield_message->get_options());
@@ -452,21 +453,12 @@ void wamp_dealer::process_yield_message(const wamp_session_id& session_id,
     wamp_result_details result_details;
     if (yield_options.get_option_or("progress", false)) {
         result_details.set_detail("progress", true);
-    } else {
-        pending_callee_invocations_itr->second.erase(request_id);
     }

-    auto pending_caller_invocations_itr =
-            m_pending_caller_invocations.find(session->get_session_id());
-    if (pending_caller_invocations_itr == m_pending_caller_invocations.end()) {
-        throw std::logic_error("dealer pending caller invocations out of sync");
-    }
-    pending_caller_invocations_itr->second.erase(request_id);
-
     std::unique_ptr<wamp_result_message> result_message(
             new wamp_result_message(std::move(yield_message->release_zone())));
     result_message->set_request_id(dealer_invocation->get_request_id());
-    result_message->set_details(result_details.marshal(yield_message->get_zone()));
+    result_message->set_details(result_details.marshal(result_message->get_zone()));
     result_message->set_arguments(yield_message->get_arguments());
     result_message->set_arguments_kw(yield_message->get_arguments_kw());

@@ -483,9 +475,11 @@ void wamp_dealer::process_yield_message(const wamp_session_id& session_id,
     // will detach the session. When this happens the pending invocations
     // be cleaned up. So we don't use an iterator here to erase the pending
     // invocation because it may have just been invalidated above.
-    m_pending_callee_invocations[session_id].erase(request_id);
-    m_pending_caller_invocations[session->get_session_id()].erase(request_id);
-    m_pending_invocations.erase(request_id);
+    if (!yield_options.get_option_or("progress", false)) {
+        m_pending_callee_invocations[session_id].erase(request_id);
+        m_pending_caller_invocations[session->get_session_id()].erase(request_id);
+        m_pending_invocations.erase(request_id);
+    }
 }

 void wamp_dealer::send_error(const std::unique_ptr<wamp_transport>& transport,

@estan
Copy link
Author

estan commented Jan 10, 2016

It's not terribly nice with the two yield_options.get_option_or("progress", false) tests, but there's no way around that short of moving the three .erase at the end into an } else { ... } up by the first test, which I'm not sure is OK?

@estan
Copy link
Author

estan commented Jan 10, 2016

Also, those two tests that check that m_pending_callee_invocations and m_pending_caller_invocations contains maps corresponding to the callee and caller sessions, respectively, should those not be made more thorough by also checking that the found maps contain invocations corresponding to the request? (i.e. check if the found maps both have a request_id key).

@estan
Copy link
Author

estan commented Jan 10, 2016

I mean, so the two tests would be something like

    // We can't have a pending invocation without a pending caller/callee
    // as they are tracked in a synchronized manner. So to have one without
    // the other is considered to be an error.
    auto pending_callee_invocations_itr =
        m_pending_callee_invocations.find(session_itr->second->get_session_id());
    if (pending_callee_invocations_itr == m_pending_callee_invocations.end() ||
        !pending_callee_invocations_itr->second.count(request_id)) {
        throw std::logic_error("dealer pending callee invocations out of sync");
    }
    auto pending_caller_invocations_itr =
        m_pending_caller_invocations.find(session->get_session_id());
    if (pending_caller_invocations_itr == m_pending_caller_invocations.end() ||
        !pending_caller_invocations_itr->second.count(request_id)) {
        throw std::logic_error("dealer pending caller invocations out of sync");
    }

@davidchappelle
Copy link
Collaborator

The reason that the three erases were called where they were was to keep
the related code localized. Now that we have a case for moving them down to
the bottom of the method that is fine.

These 2 calls at the bottom of the method seem to have been redundant:

486     m_pending_callee_invocations[session_id].erase(request_id);
487

m_pending_caller_invocations[session->get_session_id()].erase(request_id);

So they can just be removed. Also, good catch on checking the request_id.
With regards to the request_id, there is a check at the top of the
process_yield_message method to ensure that the request_id is known. Since
all three structures are always updated in unison, that single check should
be sufficient. Perhaps an assert would be more correct? I think that there
are a few other checks in wamp_dealer/wamp_broker where exceptions are
thrown that should likely just be asserts as well. We can tackle those in
another commit.

Can you create a pull request for my fork so that I can pull in your
changes and help out with some testing.

On Sun, Jan 10, 2016 at 8:08 AM, Elvis Stansvik notifications@github.com
wrote:

I mean, so the two tests would be something like

// We can't have a pending invocation without a pending caller/callee
// as they are tracked in a synchronized manner. So to have one without
// the other is considered to be an error.
auto pending_callee_invocations_itr =
    m_pending_callee_invocations.find(session_itr->second->get_session_id());
if (pending_callee_invocations_itr == m_pending_callee_invocations.end() ||
    !pending_callee_invocations_itr->second.count(request_id)) {
    throw std::logic_error("dealer pending callee invocations out of sync");
}
auto pending_caller_invocations_itr =
    m_pending_caller_invocations.find(session->get_session_id());
if (pending_caller_invocations_itr == m_pending_caller_invocations.end() ||
    !pending_caller_invocations_itr->second.count(request_id)) {
    throw std::logic_error("dealer pending caller invocations out of sync");
}


Reply to this email directly or view it on GitHub
#9 (comment).

@estan
Copy link
Author

estan commented Jan 10, 2016

Ah. I'll create a pull request.

But, regarding making the request_id check at the top an assert. If the comment at that check is true, perhaps that's not a good idea? The comment reads:

    // It is considered to be a normal condition if we cannot find the
    // associated invocation. Typically this occurs if the invocation
    // timed out or if the callers session has ended.
    BONEFISH_TRACE("%1%, %2%", *session_itr->second % *yield_message);
    const auto request_id = yield_message->get_request_id();
    auto pending_invocations_itr = m_pending_invocations.find(request_id);
    if (pending_invocations_itr == m_pending_invocations.end()) {
        BONEFISH_TRACE("unable to find invocation ... timed out or session closed");
        return;
    }

@estan
Copy link
Author

estan commented Jan 10, 2016

Or you meant asserts would be more correct for the m_pending_caller_invocations and m_pending_callee_invocations checks?

@estan
Copy link
Author

estan commented Jan 10, 2016

Okay, created a pull request: https://github.com/davidchappelle/bonefish/pull/1

Let me know there if I misunderstood something.

@davidchappelle
Copy link
Collaborator

Yes for the other invocation checks. They are conditions that would
indicate a coding error so an assert is more appropriate. That way we
aren't wasting cycles under normal/production operation. I am just wrapping
up the autobahn-cpp patch so I will pull in your patch this afternoon and
test against that as well.

On Sun, Jan 10, 2016 at 11:23 AM, Elvis Stansvik notifications@github.com
wrote:

Or you meant asserts would be more correct for the
m_pending_caller_invocations and m_pending_callee_invocations checks?


Reply to this email directly or view it on GitHub
#9 (comment).

@estan
Copy link
Author

estan commented Jan 10, 2016

Great. I changed them to asserts in the PR.

@pramukta
Copy link

Hey, so have been testing out the progressive call results branch on @davidchappelle 's account and found an interesting bug. I'm still investigating, trying to get an isolated case but the error looks like this:

[wamp_dealer.cpp:424][process_yield_message] session [173663057434166,twola,open], yield [25, {"progress":true}, [{"rows":0, "name":"current"}], nil]
[wamp_dealer.cpp:465][process_yield_message] session [173663057434166,twola,open], result [1801230688976896, {"progress":true}, [{"rows":0, "name":"current"}], nil]
[websocket_transport.cpp:39][send_message] sending message: result
[websocket_server_impl.cpp:221][on_message] unhandled exception: failed or incomplete serialization

The context for this is a WAMP connection between autobahn|js and bonefish, with the rpc endpoint being provided by autobahn|python. This means the frontend serialization scheme is JSON, while the backend scheme is msgpack. The message_id (25) looks like it is being sent out as big endian and then read in as a little endian uint64 or some such since:

>>> struct.unpack("<Q", struct.pack(">Q", 25))
(1801439850948198400,)

(sorry python code)

I'm still attempting to isolate a small test case but figured this much info is worth sharing until then in case the problem or solution is obvious to someone else. Thanks.

@davidchappelle
Copy link
Collaborator

Since bonefish uses msgpack-c for all internal serialization, the
conversion to big endian (network byte ordering) is done for us by msgpack
by default. When json is used, the msgpack messages are converted to json
before going out on the wire. Perhaps something is lost in the translation
from msgpack to json?

On Fri, Jan 29, 2016 at 4:29 PM, Pramukta Kumar notifications@github.com
wrote:

Hey, so have been testing out the progressive call results branch
https://github.com/davidchappelle/bonefish/tree/feature/progressive_call_results
on @davidchappelle https://github.com/davidchappelle 's account and
found an interesting bug. I'm still investigating, trying to get an
isolated case but the error looks like this:

[wamp_dealer.cpp:424][process_yield_message] session [173663057434166,twola,open], yield [25, {"progress":true}, [{"rows":0, "name":"current"}], nil]
[wamp_dealer.cpp:465][process_yield_message] session [173663057434166,twola,open], result [1801230688976896, {"progress":true}, [{"rows":0, "name":"current"}], nil]
[websocket_transport.cpp:39][send_message] sending message: result
[websocket_server_impl.cpp:221][on_message] unhandled exception: failed or incomplete serialization

The context for this is a WAMP connection between autobahn|js
http://autobahn.ws/js/ and bonefish, with the rpc endpoint being
provided by autobahn|python http://autobahn.ws/python/. This means the
frontend serialization scheme is JSON, while the backend scheme is msgpack.
The message_id (25) looks like it is being sent out as big endian and then
read in as a little endian uint64 or some such since:

struct.unpack("<Q", struct.pack(">Q", 25))
(1801439850948198400,)

(sorry python code)

I'm still attempting to isolate a small test case but figured this much
info is worth sharing until then in case the problem or solution is obvious
to someone else. Thanks.


Reply to this email directly or view it on GitHub
#9 (comment).

@pramukta
Copy link

Yeah, weird that it would show up for progressive call results and not the regular ones. I'll continue to look.

@pramukta
Copy link

Hmm, this may just be a logging artifact too.

@davidchappelle
Copy link
Collaborator

The request id comes from the cached dealer invocation. Would be curious to
see what the cached value is:

  • const auto& dealer_invocation = pending_invocations_itr->second;*
    std::shared_ptr<wamp_session> session =
    dealer_invocation->get_session();

// We can't have a pending invocation without a pending caller/callee
// as they are tracked in a synchronized manner. So to have one without
// the other is considered to be an error.

assert(m_pending_callee_invocations.count(session_itr->second->get_session_id()));
assert(m_pending_caller_invocations.count(session->get_session_id()));

wamp_yield_options yield_options;
yield_options.unmarshal(yield_message->get_options());

// You can't rely on simply assigning the yield options to the result
// details. Some yield options may only be applicable to the dealer.
// Likewise, some result details may be in addition to whatever is
// provided in the yield options. As a result, we only copy specific
// options over to the result details.
wamp_result_details result_details;
if (yield_options.get_option_or("progress", false)) {
    result_details.set_detail("progress", true);
}

std::unique_ptr<wamp_result_message> result_message(
        new

wamp_result_message(std::move(yield_message->release_zone())));

  • result_message->set_request_id(dealer_invocation->get_request_id());*

On Fri, Jan 29, 2016 at 4:37 PM, Pramukta Kumar notifications@github.com
wrote:

Hmm, this may just be a logging artifact too.


Reply to this email directly or view it on GitHub
#9 (comment).

@davidchappelle
Copy link
Collaborator

Also, running bonefish under valgrind might also be helpful in finding the
issue:

valgrind bonefish ...

On Fri, Jan 29, 2016 at 4:44 PM, David Chappelle chappedm@gmail.com wrote:

The request id comes from the cached dealer invocation. Would be curious
to see what the cached value is:

  • const auto& dealer_invocation = pending_invocations_itr->second;*
    std::shared_ptr<wamp_session> session =
    dealer_invocation->get_session();

// We can't have a pending invocation without a pending caller/callee
// as they are tracked in a synchronized manner. So to have one without
// the other is considered to be an error.

assert(m_pending_callee_invocations.count(session_itr->second->get_session_id()));
assert(m_pending_caller_invocations.count(session->get_session_id()));

wamp_yield_options yield_options;
yield_options.unmarshal(yield_message->get_options());

// You can't rely on simply assigning the yield options to the result
// details. Some yield options may only be applicable to the dealer.
// Likewise, some result details may be in addition to whatever is
// provided in the yield options. As a result, we only copy specific
// options over to the result details.
wamp_result_details result_details;
if (yield_options.get_option_or("progress", false)) {
    result_details.set_detail("progress", true);
}

std::unique_ptr<wamp_result_message> result_message(
        new

wamp_result_message(std::move(yield_message->release_zone())));

  • result_message->set_request_id(dealer_invocation->get_request_id());*

On Fri, Jan 29, 2016 at 4:37 PM, Pramukta Kumar notifications@github.com
wrote:

Hmm, this may just be a logging artifact too.


Reply to this email directly or view it on GitHub
#9 (comment).

@pramukta
Copy link

pramukta commented Feb 1, 2016

Sorry, got distracted with other things but was able to confirm that forcing both sides to use JSON (with the bonefish --no-msgpack option) made things work. Starting up working on the minimal example again.

@pramukta
Copy link

pramukta commented Feb 1, 2016

okay so those ids I posted don't even match so that was a completely ridiculous dead end. Not sure what the deal is.

@davidchappelle
Copy link
Collaborator

If you can post detailed steps on how to reproduce I can probably take a
closer look later on this evening.

On Mon, Feb 1, 2016 at 4:48 PM, Pramukta Kumar notifications@github.com
wrote:

okay so those ids I posted don't even match so that was a completely
ridiculous dead end. Not sure what the deal is.


Reply to this email directly or view it on GitHub
#9 (comment).

@pramukta
Copy link

pramukta commented Feb 1, 2016

Okay, I think I finally have the test case. Here's a slightly modified version of the autobahn progress example: bonefish-progressive-call-error.zip

Here's how to reproduce:

  1. Launch the bonefish binary with progressive call support $ daemon/bonefish -w 8080 -r crossbardemo -d
  2. Launch backend.py in an environment with autobahn python v0.12.1 installed (the latest) as well as twisted to run the example. I am using a python 2.7 conda environment: (bonefish) $ python backend.py
  3. npm install autobahn in the same folder as frontend.js. This installs v0.9.9 (this latest).
  4. Launch frontend.js: node frontend.js

The Progress: <integer> messages make it through but the Progress: {"value": <integer>} ones don't and that the bonefish logs show the unhandled exception: failed or incomplete serialization messages.

I've tried this test case on Mac OS X with nodejs v5.3, though the first time error I saw was with bonefish and python running on Linux. I was also able to see the error with everything running on Linux, but haven't run the test case in that env yet.

@pramukta
Copy link

pramukta commented Feb 1, 2016

Of course just as I send that, new info. changing the "value" key to a unicode string makes it work.

Update: Returning raw string values from anything on the AutobahnPython (msgpack) side to a AutobahnJS (JSON) component results in the serialization error. Was able to reproduce by removing some of the u'...' prefixes from the basic "arguments" rpc autobahn example. So this is not a progressive results issue.

@davidchappelle
Copy link
Collaborator

Good to know @pramukta I think I will put in some better handling for the unhandled exception that you are seeing. Then I will put together a pull request.

@jpetso jpetso closed this as completed in #34 Feb 9, 2016
nlyan pushed a commit to symless/bonefish that referenced this issue Jul 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants