alacarte-maps / alacarte

Renderer for OpenStreetMap tiles.
https://alacarte-maps.github.io/
Other
58 stars 18 forks source link

Segmentation fault when prerendering + threads > 1 #99

Open SrTobi opened 7 years ago

SrTobi commented 7 years ago

Hi,

When I use alacarte with the following config

./alacarte-maps-server -g ala.carte -t ../data/default.png -z 5 -s ../data/mapcss -n 2

I get a segmentation fault. This does not happen, if either -z is 0 or -n is 1.

Here is the gdb output:

(gdb) bt
#0  MaybeCachedString::assign (this=this@entry=0x88, other=...) at /home/tobi/workspace/.archive/alacarte/src/utils/cached_string.cpp:441
#1  0x00000000006071e9 in MaybeCachedString::operator= (this=this@entry=0x88, other=...) at /home/tobi/workspace/.archive/alacarte/src/utils/cached_string.cpp:419
#2  0x00000000005bf55c in eval::Eval<MaybeCachedString>::overwrite (this=0x7fffb000ade0, obj=obj@entry=0x7fffd38cbf10, v=v@entry=0x88) at /home/tobi/workspace/.archive/alacarte/include/server/eval/eval.hpp:129
#3  0x00000000005bee21 in Style::overmerge (this=this@entry=0x0, obj=0x7fffd38cbf10, templ=...) at /home/tobi/workspace/.archive/alacarte/src/server/style.cpp:55
#4  0x00000000005b0132 in ApplySelector::matchNode (this=0x7fffb000ab00, nodeID=..., ti=..., attributes=<optimized out>) at /home/tobi/workspace/.archive/alacarte/src/server/selectors/apply_selector.cpp:50
#5  0x00000000005afbb6 in Rule::match (this=0x7fffb000aa90, nodeIDs=..., wayIDs=..., relIDs=..., relIDs@entry=<error reading variable: Cannot access memory at address 0x7fffbc1615b0>, ti=..., 
    ti@entry=<error reading variable: Cannot access memory at address 0x7fffbc1615b8>, renderAttributes=renderAttributes@entry=0x7fffbc1616a0) at /home/tobi/workspace/.archive/alacarte/src/server/rule.cpp:51
#6  0x00000000005c1bff in Stylesheet::match (this=0x7fffb001b0c0, nodeIDs=..., wayIDs=..., relIDs=<error reading variable: Cannot access memory at address 0x7fffbc1615b0>, ti=..., 
    styleMap=styleMap@entry=0x7fffbc1616a0) at /home/tobi/workspace/.archive/alacarte/src/server/stylesheet.cpp:49
#7  0x000000000055bd27 in Job::process (this=this@entry=0x7fffbc161a50) at /home/tobi/workspace/.archive/alacarte/src/server/job.cpp:193
#8  0x00000000005ab4eb in RequestManager::nextPreRenderRequest (this=this@entry=0x8cc840) at /home/tobi/workspace/.archive/alacarte/src/server/request_manager.cpp:265
#9  0x00000000005ac060 in RequestManager::processNextRequest (this=0x8cc840) at /home/tobi/workspace/.archive/alacarte/src/server/request_manager.cpp:172
#10 0x00000000005ac631 in boost::_mfi::mf0<void, RequestManager>::call<boost::shared_ptr<RequestManager> > (u=<synthetic pointer>..., this=<optimized out>) at /usr/include/boost/bind/mem_fn_template.hpp:40
#11 boost::_mfi::mf0<void, RequestManager>::operator()<boost::shared_ptr<RequestManager> > (u=<synthetic pointer>..., this=<optimized out>) at /usr/include/boost/bind/mem_fn_template.hpp:55
#12 boost::_bi::list1<boost::_bi::value<boost::shared_ptr<RequestManager> > >::operator()<boost::_mfi::mf0<void, RequestManager>, boost::_bi::list0> (a=<synthetic pointer>..., f=<synthetic pointer>..., 
    this=<synthetic pointer>) at /usr/include/boost/bind/bind.hpp:259
#13 boost::_bi::bind_t<void, boost::_mfi::mf0<void, RequestManager>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<RequestManager> > > >::operator() (this=<synthetic pointer>)
    at /usr/include/boost/bind/bind.hpp:1294
#14 boost::asio::asio_handler_invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, RequestManager>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<RequestManager> > > > > (
    function=<synthetic pointer>...) at /usr/include/boost/asio/handler_invoke_hook.hpp:69
#15 boost_asio_handler_invoke_helpers::invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, RequestManager>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<RequestManager> > > >, boost::_bi::bind_t<void, boost::_mfi::mf0<void, RequestManager>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<RequestManager> > > > > (context=<synthetic pointer>..., function=<synthetic pointer>...)
    at /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:37
#16 boost::asio::detail::completion_handler<boost::_bi::bind_t<void, boost::_mfi::mf0<void, RequestManager>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<RequestManager> > > > >::do_complete (
    owner=0x8ccab0, base=<optimized out>) at /usr/include/boost/asio/detail/completion_handler.hpp:68
#17 0x00000000005ad380 in boost::asio::detail::task_io_service_operation::complete (bytes_transferred=0, ec=..., owner=..., this=<optimized out>)
    at /usr/include/boost/asio/detail/task_io_service_operation.hpp:38
#18 boost::asio::detail::task_io_service::do_run_one (ec=..., this_thread=..., lock=..., this=0x8ccab0) at /usr/include/boost/asio/detail/impl/task_io_service.ipp:372
#19 boost::asio::detail::task_io_service::run (ec=..., this=0x8ccab0) at /usr/include/boost/asio/detail/impl/task_io_service.ipp:149
#20 boost::asio::io_service::run (this=<optimized out>) at /usr/include/boost/asio/impl/io_service.ipp:59
#21 0x00007ffff77a698d in ?? () from /usr/lib/libboost_thread.so.1.63.0
#22 0x00007ffff5a10454 in start_thread () from /usr/lib/libpthread.so.0
#23 0x00007ffff4eb07df in clone () from /usr/lib/libc.so.6
(gdb) p this
$3 = (MaybeCachedString * const) 0x88
(gdb) p other
$4 = (const MaybeCachedString &) <error reading variable>
(gdb) p &other
$5 = (const MaybeCachedString *) 0x7fffb000ade8
(gdb) list
436  * @brief Assigns a maybe cached string
437  *
438  **/
439 void MaybeCachedString::assign( const MaybeCachedString& other )
440 {
441     reset();       // <-------------- somewhere around here the segfault happens
442     cached = other.cached;
443     if (cached) {
444         internalString = other.internalString;
445     } else {
446         internalString = new StringStorageElement(*other.internalString);
447     }
448 }
449 
450 /**
451  * @brief Assigns a cached string
452  *
453  **/
454 void MaybeCachedString::assign( const CachedString& other )
455 {

Can someone verify this?

SrTobi commented 7 years ago

If I am not mistaken, this is the exact same error I get under windows (mentioned in #75)

Scheirle commented 7 years ago

Can't reproduce it here (with bawue.osm and karlsruhe_big.osm) so it is a bit hard to debug, but Style::overmerge (style.cpp:38) looks suspicious.

There is something like:

const shared_ptr<StyleTemplate>& templ = ...;
templ->image->overwrite(obj, &(this->image));

So we are calling eval::Eval<MaybeCachedString>::overwrite and pass a pointer to this->image to it.

eval::Eval<MaybeCachedString>::overwrite does now modify the given Pointer (&(this->image)) (eval.hpp:129)

Therefore calling Style::overmerge from different threads is critical. But we are doing just that Job::process -> Stylesheet::match -> Rule::match -> Selector::matchNode/Way/Relation -> Style::overmerge

Please keep in mind I'm not very familiar with the style code, so I may have overlooked something obvious.