boost::asio - Asynchroner Aufruf nach beenden des sockets
-
Hmm. Danke für das Beispiel.
Werds mir bestimmt genauer anschauen.Aber wo meinst du sind sonst noch Fehler?
Und irgendwie will ich schon noch wissen, was an obigem Code explizit den Fehler verursacht. Wie du ja sagts müssten die Handler, die per post aufgerufen werden der Reihe nach korrekt aufgerufen werden, was ja anscheinend nicht wirklich passiert.
Potentiell glaube ich dir schon, dass es Fehler drin hat, aber was ruft mir denn jetzt den Fehler hervor? (konntest du ihn überhaupt auch mal nach vollziehen?)
-
Tachyon schrieb:
Der Code hat einiger Fehler.
Nur, um mal eine potentielle Quelle zu nennen:
void restart ( unsigned int size ) { //hier drin werden Dinge über post() asynchron gestartet cleanup (); //das hier läuft aber in einem anderen Thread buffer = std::vector<char> ( size ); start (); }
Kann es sein, dass du in
cleanup
dasrun_thread->join()
übersehen hast? Wenn die Kopie durchgeführt wird, sollte eigentlich nur noch ein Thread laufen@drakon,
Ich kompiliere mal Boost 1.41.0 ... das dauert aber ein wenigGrüssli
-
Dravere schrieb:
@drakon,
Ich kompiliere mal Boost 1.41.0 ... das dauert aber ein wenigGrüssli
Lad dir doch die Binary?
-
drakon schrieb:
Lad dir doch die Binary?
Und mich dort registrieren? Keine Lust! Über bjam kann man die Sache ja einfach kompilieren, man muss dann halt nur ein wenig warten, aber was solls? Meine beiden Kerne werden zusammen nie wirklich über 70% belastet, kann man noch wunderbar daneben arbeiten.
Jedenfalls habe ich es nun mit Boost 1.41.0 getestet. Irgendwas machst du verkehrt, ich kann dir nur nicht sagen was, da es bei mir wunderbar funktioniert
Ich starte gerade noch meinen Testcomputer, dort habe ich noch ein Win7 x86 und ein WinXP x86 drauf. Teste mal die Sache noch dort drüben, ob es dort irgendeinen Fehler gibtGrüssli
-
drakon schrieb:
Und nein. An
cout
liegst nicht, wenn ich kriege den Fehler ja aufgrund von einem Speicherzugriffsfehler in vector. Die Ausgabe habe ich nur da, damit man es besser sehen kann.Kannst du mir noch was genaueres zu diesem Speicherzugriffsfehler sagen? Wo passiert der genau?
Der Fehler mit der Ausgabe auf der Konsole liegt meiner Meinung nach an der Konsole selber, also dieser hier:
http://dl.dropbox.com/u/1716912/udp_error.jpg
Wenn du bei der Ausgabe der Nachricht"server"
mehrere Ausgaben machst (z.B.std::cout << std::clock() << ' ' << "server";
), erkennt man sehr schön, wie sich zum Teil dieserver
&error
Nachrichten überlagern. Zumindest auf WinXP ist dies immer mal wieder passiert, mit Win7 konnte ich nicht mal das reproduzieren. Daher könnte ich mir gut vorstellen, dass es nur ein Problem der XP Konsole ist. Müsste man mal genauer nachforschen gehen, wie die bei multithread Anwendungen reagiert.Den Speicherzugrifffehler konnte ich allerdings mit dem gezeigten Code nie reproduzieren, also trat bei mir nie auf.
Grüssli
-
trace:
msvcp90d.dll!104ed4c3() [Unten angegebene Rahmen sind möglicherweise nicht korrekt und/oder fehlen, keine Symbole geladen für msvcp90d.dll] > udp_error.exe!std::_Vector_const_iterator<char,std::allocator<char> >::operator*() Zeile 98 + 0x14 Bytes C++ udp_error.exe!std::_Vector_iterator<char,std::allocator<char> >::operator*() Zeile 340 C++ udp_error.exe!boost::asio::detail::buffer_debug_check<std::_Vector_iterator<char,std::allocator<char> > >::operator()() Zeile 446 C++ udp_error.exe!boost::detail::function::void_function_obj_invoker0<boost::asio::detail::buffer_debug_check<std::_Vector_iterator<char,std::allocator<char> > >,void>::invoke(boost::detail::function::function_buffer & function_obj_ptr={...}) Zeile 154 C++ udp_error.exe!boost::function0<void>::operator()() Zeile 1013 + 0x16 Bytes C++ udp_error.exe!boost::asio::detail::buffer_cast_helper(const boost::asio::mutable_buffer & b={...}) Zeile 124 C++ udp_error.exe!boost::asio::buffer_cast<char *>(const boost::asio::mutable_buffer & b={...}) Zeile 141 + 0x9 Bytes C++ udp_error.exe!boost::asio::detail::win_iocp_socket_service<boost::asio::ip::udp>::receive_from_operation<boost::asio::mutable_buffers_1,void (__cdecl*)(boost::system::error_code const &,unsigned int)>::do_completion_impl(boost::asio::detail::win_iocp_io_service::operation * op=0x00346f48, unsigned long last_error=995, unsigned int bytes_transferred=0) Zeile 1643 + 0x9 Bytes C++ udp_error.exe!boost::asio::detail::win_iocp_io_service::operation::do_completion(unsigned long last_error=995, unsigned int bytes_transferred=0) Zeile 77 + 0x16 Bytes C++ udp_error.exe!boost::asio::detail::win_iocp_io_service::do_one(bool block=true, boost::system::error_code & ec={...}) Zeile 512 C++ udp_error.exe!boost::asio::detail::win_iocp_io_service::run(boost::system::error_code & ec={...}) Zeile 186 + 0xe Bytes C++ udp_error.exe!boost::asio::io_service::run() Zeile 58 + 0xf Bytes C++ udp_error.exe!run(boost::asio::io_service * s=0x00467638) Zeile 56 C++ udp_error.exe!boost::_bi::list1<boost::_bi::value<boost::asio::io_service *> >::operator()<void (__cdecl*)(boost::asio::io_service *),boost::_bi::list0>(boost::_bi::type<void> __formal={...}, void (boost::asio::io_service *)* & f=0x0041c9ab, boost::_bi::list0 & a={...}, boost::_bi::type<void> __formal={...}) Zeile 246 + 0x23 Bytes C++ udp_error.exe!boost::_bi::bind_t<void,void (__cdecl*)(boost::asio::io_service *),boost::_bi::list1<boost::_bi::value<boost::asio::io_service *> > >::operator()() Zeile 21 C++ udp_error.exe!boost::detail::thread_data<boost::_bi::bind_t<void,void (__cdecl*)(boost::asio::io_service *),boost::_bi::list1<boost::_bi::value<boost::asio::io_service *> > > >::run() Zeile 57 C++ udp_error.exe!boost::`anonymous namespace'::thread_start_function(void * param=0x0015cbc8) Zeile 168 C++ msvcr90d.dll!1023dfd3() msvcr90d.dll!1023df69() kernel32.dll!7c80b729()
Also ich kriege den Zugriffsfehler auch wenn ich keine Ausgabe habe. (Ursprünglich war da ja keine, sondern die habe ich für das nachvollziehen eingebaut).
-
Bei mir funktioniert drakons Code so wie gepostet nicht. Ich bekomme Assertions aufgrund ungültiger Vektor-Iteratoren, wenn ich quit eingebe.
Mit demjoin()
hast Du allerdings recht. Ich werde mir das bei Gelegenheit nochmal genauer ansehen.
-
Tachyon schrieb:
Bei mir funktioniert drakons Code so wie gepostet nicht. Ich bekomme Assertions aufgrund ungültiger Vektor-Iteratoren, wenn ich quit eingebe.
Mit demjoin()
hast Du allerdings recht. Ich werde mir das bei Gelegenheit nochmal genauer ansehen.Genau die bekomme ich eben auch.
Danke für die Mühe.
-
Ich habe mich gerade gefragt, ob es womöglich an Boost.Thread liegen könnte, dass da der
join
nicht richtig funktioniert. Konnte allerdings keine entsprechende Themen dazu in der Mailing Liste von Boost.User finden. Ich schau mir das auch noch etwas genauer an, komme bei meinem eigenen Problem grad auch nicht weiter, daher lenke ich mich jetzt mal damit abGrüssli
-
Bei denen, wo der Fehler auftritt:
Probiert mal den Code ohneio_service::stop
aufzurufen. Also diecleanup
Funktion so umzubauen:void cleanup () { // böse io_service.post ( boost::bind ( &udp::socket::shutdown, &socket_, udp::socket::shutdown_both ) ); io_service.post ( boost::bind ( &udp::socket::close, &socket_ ) ); // anscheinend ok //socket_.shutdown ( udp::socket::shutdown_both ); //socket_.close (); // v v v v auskommentieren v v v v v v v v v v v v v v v v v v v v v v v v v v v //io_service.post ( boost::bind ( &boost::asio::io_service::stop, &io_service) ); run_thread->join (); io_service.reset (); std::cout << "cleanup finished\n"; }
Sobald keine Aufgaben mehr in der Liste sind, gibt
io_service::run
sowieso zurück. Und ich habe gerade von einem Fall gelesen, wo einio_service::stop
zu einem fehlerhaftenthread::join
geführt hat. Wieso genau, wusste aber niemand. Die Chance ist zwar gering, aber versuchen schadet ja nichtGrüssli
-
Hmm. Ok. Beim ersten "quit" habe ich den Fehler nicht mehr nachvollziehen können, allerdings ist 1 mal ein vector Zugriffsfehler beim zweiten mal "quit" gekommen. Allerdings war die Reihenfolge korrekt und es gab auch nicht den gleichen Stacktrace..
Ist mal wieder typisch, dass ich einen merkwürdigen Fehler entdecken darf.. -.-
-
Tachyon schrieb:
Soll heißen: Wenn Du einen Handler über irgendeine asynchrone Operation in die Queue schiebst, wird dieser erst ausgeführt, wenn Du
run()
,run_one()
, [c]poll()[/c] oderpoll_one()
für das benutzteio_service
-Objekt aufrufst.ich hätte da noch eine grundsätzliche verständnisfrage zu poll:
ich habe ein liste mit webclient objekte (verwende den async_webclient von boost)
wenn ich nun gleichzeitig aus meiner webclientliste mehrere inhalte einer url downloaden möchte, dann blockiert ja run sich gegenseitig, also habe ich mir gedacht, dass könnte mit poll gehen, oder?! aber wie genau funktioniert poll? wann weiß ich, dass alles abgearbeitet wurde? oder kann ich eine totale non-blocking abarbeitung (also download von meine url-inhalten) nur mittels threads machen die run ausführen?!
danke für die erklärungen und hilfe
lg