boost::asio - Asynchroner Aufruf nach beenden des sockets
-
Hallo
Ich habe die Vermutung einen Bug in boost::asio gefunden zu haben.
Prinzipiell mache ich folgendes:
boost::asio::io_service io_service; boost::asio::ip::udp::socket socket; ... socket.open (..); socket.bind (..); socket.async_receive_from (..); io_service.run (); ... // ich mache ein paar erfolgreiche receives // in einem anderen thread: io_service.stop (); thread.join (); // stellt sicher, dass io_service.run zurückgekehrt ist io_service.reset (); socket.shutdown ( shutdown_both ); socket.close (); io_service.run (); // und nochmal: merke, dass der socket nicht mal mehr geöffnet wurde // und hier bekomme ich doch wieder ein async_receive_from () Aufruf.
Es wird also eine asynchrone Operation ausgeführt, obwohl ich den io_service zurückgesetzt habe und ebenfalls den socket runtergefahren. Und in der Doku für shutdown steht eindeutig:
Disable sends or receives on the socket.
Natürlich kommt nur ein Fehler an:
Der E/A-Vorgang wurde wegen eines Threadendes oder einer Anwendungsanforderung abgebrochen
Ist das jetzt ein Bug oder hat noch jemand eine gute Idee?
-
Du musst
shutdown
+close
aufrufen, solange die Eventloop vomio_service
aktiv ist. Wenn Du die Eventloop abwürgst, dann können auch keine Handler mehr darin ausgeführt werden, und daher kann die von Dir gestartete asynchrone Operation auch nicht mehr auf dasclose()
reagieren.Probiers mal so:
boost::asio::io_service io_service; boost::asio::ip::udp::socket socket; ... socket.open (..); socket.bind (..); socket.async_receive_from (..); io_service.run (); ... // ich mache ein paar erfolgreiche receives // in einem anderen thread: //shutdown und close in den Eventhandler hängen (besser noch die passende io_service-Instanz mit socket.get_io_service() besorgen) io_service.post(boost::bind(&udp::socket::shutdown, &socket, udp::socket::shutdown_both )); io_service.post(boost::bind(&udp::socket::close, &socket)); //der auf dem Socket aktive Handler kommt mit operation_aborted zurück io_service.post(boost::bind(&io_service::stop, &io_service)); //Aufruf von io_service::stop queuen, sonst kann es passieren, dass die oben eingereihten Handler nicht mehr ausgeführt werden thread.join (); // stellt sicher, dass io_service.run zurückgekehrt ist io_service.reset (); io_service.run (); // und nochmal: merke, dass der socket nicht mal mehr geöffnet wurde // und hier bekomme ich doch wieder ein async_receive_from () Aufruf.
PS: Wieso beendest Du die Eventloop vom io_service überhaupt?
-
Guter Vorschlag, aber zuerst hatte ich das shutdown und close noch vor dem stop des io_service. Aber auch mit dem post habe ich das selbe Problem. Der Aufruf kommt nachdem ich alles runtergefahren habe.
Ich fahre den runter, damit ich alles im Sinne eines reset wieder herstellen kann. Also den socket z.B auf einen anderen Port o.ä zu connecten.
Das Problem ist halt, dass wenn nach dem runterfahren ein Funktionsaufruf kommt, dass intern ja noch auf einen Buffer zugegriffen wird, welcher aber nicht mehr gültig ist, weil ich den eben ebenfalls zurücksetzen (leeren) möchte./EDIT:
post ist ja sowieso ebenfalls dazu da den Aufruf asynchron zu machen. Er kehrt ja einafach sofort zurück.
-
drakon schrieb:
Guter Vorschlag, aber zuerst hatte ich das shutdown und close noch vor dem stop des io_service. Aber auch mit dem post habe ich das selbe Problem. Der Aufruf kommt nachdem ich alles runtergefahren habe.
Welcher Aufruf?
Grundsätzlich: Du musst eine
io_service
-Instanz die eine aktive Eventloop hat nicht beenden, um neue Sockets hinzuzufügen oder zu entfernen oder zu schließen oder neu zu öffnen. Das kannst Du alles auch machen, während derio_service
aktiv ist.io_service::post()
synchronisert die Aufrufe vor allem in die Eventqueue vom io_service. Es geht darum, die auszuführenden Handler zu queuen und sie sequentialisieren. Es geht nicht darum, non-blocking Calls zu bekommen (dafür kann man es natürlich ebenfalls benutzen).Im Quelltext oben wird also erst
socket::shutdown()
, dannsocket::close()
und dannio_service::stop()
in die Eventqueue vomio_service
geschoben. Die Handler werden dann nach FIFO-Strategie ausgeführt, und zwar im Konext des io_service-Threads.Wenn Du
io_service::stop()
aufrufst, killst Du den Thread, der die Eventhandler abarbeitet. Die Queue darin kann also nicht mehr geleert werden.io_service::reset()
leert die Queue nicht, sondern setzt nur ein paar Flags zurück, ähnlich wieclear()
bei den Streams aus der Standardlib.
Dementsprechend werden noch eingereihte Handler ausgeführt, wenn Du erneut io_service::run aufrufst. Das ist dann der Effekt "dass der Aufruf kommt, nachdem Du alles heruntergefahren hast" (dassocket.close()
schlägt durch und der Handler kommt mitoperation_aborted
zurück).Vielleicht sollte ich mal einen Artikel zu boost.asio schreiben...
-
drakon schrieb:
Ich fahre den runter, damit ich alles im Sinne eines reset wieder herstellen kann. Also den socket z.B auf einen anderen Port o.ä zu connecten.
Darf ich fragen, wieso du das Socket wiederverwenden willst? Bei solchen Dingen erstelle ich lieber gleich was neues. Der Overhead ist minimal, dafür hat man eben keine solchen Probleme. Ist das Gleiche wie mit den In-/Output Streams der Standardbibliothek. Erspart einem eine Menge an Ärger.
Tachyon schrieb:
Vielleicht sollte ich mal einen Artikel zu boost.asio schreiben...
http://www.c-plusplus.net/forum/viewtopic-var-t-is-213365.html
Grüssli
-
Tachyon schrieb:
Welcher Aufruf?
Der asynchrone Aufruf, dass etwas beendet wurde. (mit der obigen Meldung).
Grundsätzlich: Du musst eine
io_service
-Instanz die eine aktive Eventloop hat nicht beenden, um neue Sockets hinzuzufügen oder zu entfernen oder zu schließen oder neu zu öffnen. Das kannst Du alles auch machen, während derio_service
aktiv ist.io_service::post()
synchronisert die Aufrufe vor allem in die Eventqueue vom io_service. Es geht darum, die auszuführenden Handler zu queuen und sie sequentialisieren. Es geht nicht darum, non-blocking Calls zu bekommen (dafür kann man es natürlich ebenfalls benutzen).Im Quelltext oben wird also erst
socket::shutdown()
, dannsocket::close()
und dannio_service::stop()
in die Eventqueue vomio_service
geschoben. Die Handler werden dann nach FIFO-Strategie ausgeführt, und zwar im Konext des io_service-Threads.Wenn Du
io_service::stop()
aufrufst, killst Du den Thread, der die Eventhandler abarbeitet. Die Queue darin kann also nicht mehr geleert werden.io_service::reset()
leert die Queue nicht, sondern setzt nur ein paar Flags zurück, ähnlich wieclear()
bei den Streams aus der Standardlib.
Dementsprechend werden noch eingereihte Handler ausgeführt, wenn Du erneut io_service::run aufrufst. Das ist dann der Effekt "dass der Aufruf kommt, nachdem Du alles heruntergefahren hast" (dassocket.close()
schlägt durch und der Handler kommt mitoperation_aborted
zurück).Ok, das macht Sinn. Das konnte ich leider aus der Doku nicht lesen.. Woher hast du denn das?
Danke, ich habe vorhin anscheindend das stop nicht in die post eingereiht gehabt. Jetzt gehts.
Dann ist demfall die Doku einfach nicht zu gebrauchen. Denn hier steht rein gar nichts von einem io_service, also gehe ich davon aus, dass das gemacht wird, was da steht..
@Dravere:
Ich weiss nicht recht. Es ist denke ich mehr aus Prinzip, weil ich dachte, dass es gehen sollte und jetzt will ichs so haben und kein Workaround.
Das zurücksetzen usw. läuft ja einwandfrei. Es war halt eben lediglich das mit dem queuing der Calls.Danke auf jeden Fall nochmal an dich Tachyon!
-
drakon schrieb:
Dann ist demfall die Doku einfach nicht zu gebrauchen. Denn hier steht rein gar nichts von einem io_service, also gehe ich davon aus, dass das gemacht wird, was da steht..
Zugegeben: Die Doku ist manchmal etwas arg dünn.
socket::shutdown()
sorgt allerdings erstmal nur dafür, dass man Senden, Empfangen oder beides für einen Socket ausknipsen kann. Dadurch kommt es nicht zu dem "Fehler".Der Fehler ist auch kein Fehler, sondern das korrekte Verhalten von
socket::close()
:basic_datagram_socket::close schrieb:
This function is used to close the socket. Any asynchronous send, receive or connect operations will be cancelled immediately, and will complete with the boost::asio::error::operation_aborted error.
Der E/A-Vorgang wurde wegen eines Threadendes oder einer Anwendungsanforderung abgebrochen ist die Win-API Meldung zu
opearation_aborted
.drakon schrieb:
Ok, das macht Sinn. Das konnte ich leider aus der Doku nicht lesen.. Woher hast du denn das?
Die Sache mit dem
io_service::post()
habe ich aus der Doku. In den Beispielen ist das ein häufig verwendetes Pattern. Außer io_service ist fast keine asio-Klasse threadsafe. Deshalb müssen potentiell konkurrierende Aufrufe von Memberfunktionen auf Objekte dieser Klassen synchronisiert werden. Guck Dir z.B. mal die Close-Funktion aus dem Chat-Client Beispiel an.Das mit der Queue und der Arbeitsweise der asynchronen Operationen habe ich aus der boost.asio-Übersicht. Da wo das Proactor-Pattern beschrieben wird.
-
Naja. Ich habe das dort eben so verstanden, dass innerhalb von close die Funktionen mit dem error aufgerufen werden sollten. Das verstehe ich unter immediately. Da steht ja nichts davon, dass die Aufrufe in die queue eingereiht werden..
Etwas ist mir aber nicht ganz klar. Warum synchronisiert du die Aufrufe von socket::shutdown und socket::close? - Es reicht ja dafür zu sorgen, dass io_service::stop erst am Ende ausgeführt wird. Habs mal getestet und funktionieren tuts auch.
Und sehe ich das richtig, dass socket::cancel hier wirklich sofort die Handler beendet und somit eher das Mittel der Wahl wäre? (ich habe XP, darum kann ichs nicht testen).
Ja. Die Doku ist mir wirklich zu mager. Aber abgesehen von der boost Seite und den Beispielen hast du auch nichts anderes mehr gefunden? (Ich habe auch mal ein wenig gesucht und hatte einfach das Gefühl, dass asio kaum wer braucht. ;))
-
Handler werden grundsätzlich über den Dispatacher vom
io_service
ausgeführt.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()
,poll()
oderpoll_one()
für das benutzteio_service
-Objekt aufrufst.Due Aufrufe von
shutdown()
undclose()
müssen synchronisiert werden, weil sie sonst potentiell parallel zur Abarbeitung z.B. einesasync_receive
passieren können. Wenn gerade ein empfangenes Datagramm bearbeitet wird (vom Socket), und Du gleichzeitig z.B.close()
auf den Socket aufrufst, dann hast Du eine klassische Race Condition. Die geteilte Resource ist dabei der Socket selbst und es greifen zwei Threads drauf zu (der vomio_service
der gerade das async_receive bearbeitet, und der, derclose()
aufruft).Wieso kannst Du es mit Win-XP nicht testen? -> Achja, cancel() geht da ja nicht.
-
Naja, wegen der mangelnden Unterstützung, die in den Remarks vermekt ist.
-
Tja.. Tachyon.. Ich befürchte, dass es doch nicht so einfach war.
Ich habe das selbe Fehlerbild, aber jetzt in einer einfacheren Situation bekommen.
Wenn ich nämlich jetzt gar keine receives mehr empfange und gleich resetten will, dann funktioniert das mit dem posten von shutdown und close nicht. Aus irgendeinem Grund kommt manchmal die Abbruch Meldung trotzdem erst wenn der service wieder gestartet ist (es war also ein Handler nach io_service::stop drin..). Das konnte ich bis jetzt nicht beobachten, wenn ich die calls einfach ohne post gemacht habe.
// 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 gut: socket_.shutdown ( udp::socket::shutdown_both ); socket_.close (); io_service_.post ( boost::bind ( &boost::asio::io_service::stop, &io_service_) ); run_thread_->join (); io_service_.reset ();
Dabei müssten ja die die beiden calls tatsächlich vor dem io_service::stop kommen.. Für mich macht das ganze irgendwie keinen Sinn mehr..
-
Sollte es nicht so laufen?
1. shutdown socket (nur receive seite)
2. receive handler wird aufgerufen mit error eof, bzw. bytes_transferred == 0
3. close socket im receive handlerOder bin ich irgendwie ganz falsch gewickelt.
Simon
-
Kannst du mal ein minimales Beispiel zeigen, wo der Fehler passiert? Wenn ich Zeit finde, möchte ich das heute mal durchtesten.
Grüssli
PS: Es kam schon wieder eine neue Boost Version raus ...
-
@theta:
Da tachyon noch nichts gesagt hat und in der boost Doku nix davon steht, gehe ich davon aus, dass es schon so geht..@dravere:
Ja, werde ich wahrscheinlich heute Abend noch machen. Im Moment habe ich ein paar andere Sachen im Kopf.
-
drakon schrieb:
Wenn ich nämlich jetzt gar keine receives mehr empfange und gleich resetten will, dann funktioniert das mit dem posten von shutdown und close nicht.
Das sollte eigentlich immer funktionieren. Voraussetzung dafür ist allerdings, dass Du einen
io_service
mit aktivem Eventprozessor hast. Wenn nicht, dann tutpost()
genau gar nichts.drakon schrieb:
Aus irgendeinem Grund kommt manchmal die Abbruch Meldung trotzdem erst wenn der service wieder gestartet ist (es war also ein Handler nach io_service::stop drin..). Das konnte ich bis jetzt nicht beobachten, wenn ich die calls einfach ohne post gemacht habe.
Das darf so nicht sein. Ich glaube, Du solltest doch mal deutlich mehr Code zeigen. Vor allem den, wo Du die asynchronen Operationen startest.
// anscheinend gut: socket_.shutdown ( udp::socket::shutdown_both ); socket_.close (); //nein, sehr schlecht. sockets sind nicht threadsafe, und Du greifst mit zwei //Threads drauf zu (der aus dem Eventprozessor, und der, der close() aufruft-
Ich stelle nochmal die Frage:
Wieso beendest Du denio_service
? Du kannst auch bei laufendem Eventprozessor die sockets schließen und wieder neu öffnen. Noch besser wäre, wie hier bereits gesagt wurde, das Socketobjekt komplett neu zu erstellen.
-
Das der Zugriff da nicht synchronisiert ist, ist mir klar, allerdings habe ich, wie gesagt den Fehler so nicht reproduzieren können, daher "anscheinend gut".
Das ich da den io_service neu starte muss wohl nicht sein, ja, aber ich dachte halt zuerst eben, dass es nötig seie, oder zumindest gut ginge. Im Moment brauche ich das vor allem, um sicher zu gehen, dass auch alle Handler durch sind und warte daher bis der Thread zurück kommt und starte ihn neu. Ich denke, dass man das mit io_service::poll auch erreichen kann, aber jetzt will ich zuerst das hier zum laufen kriegen.
#include <iostream> #include <vector> #include <string> #define _WIN32_WINNT 0x0501 #include <boost/asio/io_service.hpp> #include <boost/asio/ip/udp.hpp> #include <boost/asio/buffer.hpp> #include <boost/thread.hpp> #include <boost/system/error_code.hpp> #include <boost/bind.hpp> using boost::asio::ip::udp; boost::asio::io_service io_service; std::vector<char> buffer ( 64 ); std::vector<char> send_buffer ( 64 ); boost::asio::ip::udp::socket socket_ ( io_service ); boost::asio::ip::udp::endpoint remote_endpoint ; std::auto_ptr<boost::thread> run_thread; void start (); void received ( const boost::system::error_code& error, std::size_t bytes_received ); void cleanup (); void restart ( unsigned int size ); void receiving () { socket_.async_receive_from ( boost::asio::buffer ( buffer ), remote_endpoint, &received ); } void sent ( const boost::system::error_code& error, std::size_t bytes_sent ) { receiving (); } void received ( const boost::system::error_code& error, std::size_t bytes_received ) { if ( !error ) { std::string answer = "tag"; send_buffer = std::vector<char> ( answer.begin (), answer.end () ); socket_.async_send_to ( boost::asio::buffer ( send_buffer ), remote_endpoint, &sent ); } else std::cout << "error - received " << error.message () << "\n"; } void run ( boost::asio::io_service* s ) { s->run (); } void restart ( unsigned int size ) { cleanup (); // auskommentieren, damit die Meldung ausgegeben wird buffer = std::vector<char> ( size ); start (); } void start () { socket_.open ( udp::v4 () ); socket_.bind ( udp::endpoint ( udp::v4 (), 33333) ); receiving (); run_thread.reset ( new boost::thread ( boost::bind ( &run, &io_service ) ) ); } 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 (); io_service.post ( boost::bind ( &boost::asio::io_service::stop, &io_service) ); run_thread->join (); io_service.reset (); std::cout << "cleanup finished\n"; } /* Korrekterweise sollte zuerst "server" ausgegeben werden, dann bei der eingabe von "quit" sollte die error Meldung ausgegeben werden und erst dann "cleanup finished". Allerdings kommt es vor, dass bei den post-Varianten zuerst "cleanup finished" kommt, dann "server" und erst dann kommt die error Meldung, dass eine Verbindung unterbrochen wurde. Respektive es kommt eine Laufzeitmeldung, dass vector nicht dereferenziert werden kann, was daher kommt, dass der buffer in restart invalidiert wird, was kein Problem ist, wenn die Meldung noch innerhalb von cleanup vorkommt. */ int main () { start (); for (int i = 0; i < 2; ++i) { std::cout << "server\n"; for (;;) { std::string c; std::cin >> c; if ( c == "quit" ) break; } restart ( 64 ); } }
Und so siehts dann manchmal aus:
http://dl.dropbox.com/u/1716912/udp_error.jpg
-
Was heisst manchmal? Habe es nun 100 Mal getestet, konnte das Verhalten nicht reproduzieren:
Win7 64 Bit, MSVC 9.0 (2008), Boost 1.42.0 (ganz frisch geholt).Wobei bei 1.42.0 anscheinend ein paar Bugs behoben wurden, welche womöglich mit dem Problem zusammenhängen könnten, bin mir aber nicht ganz sicher:
http://www.boost.org/doc/libs/1_42_0/doc/html/boost_asio/history.htmlWelche Version verwendest du denn? Dann kann ich es allenfalls noch mit der probieren, müsste ich allerdings auch zuerst noch kompilieren.
Die einzige Sache, wo ich nicht so genau weiss, wie das eigentlich aussieht und mir hier auffällt: Wie sieht die Synchronisation von
std::cout
über mehrere Threads aus? Könnte es ein Problem sein, dass da eine Nachricht im Puffer verbleibt und dann eine andere Nachricht zuerst auftaucht, obwohl sie erst später geschrieben wurde? Kenne mich da zu wenig aus. Vielleicht noch bei jeder Ausgabestd::endl
verwenden und einstd::clock
Stempel dazuGrüssli
-
Also ich kann das sehr gut nachvollziehen, wenn ich einfach sobald das Fenster aufgeht "quit" mache. Dann brauche ich da 2-3x zu versuchen und ich habe einen Fehler.
Ich habe die 1.41 Version.
Kann sein, dass was behoben wurde, habe was gelesen in der changelog:Fixed a problem with the lifetime of handler memory, where Windows needs the OVERLAPPED structure to be valid until both the initiating function call has returned and the completion packet has been delivered.
Das Problem bei mir hat ja was mit dem memory zu tun, allerdings wird bei mir ja nicht der Speicher direkt falsch behandelt, sondern eben nur der Handler kommt zu spät.
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.
-
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 (); }
Probier es mal so:
#include <iostream> #include <vector> #include <string> #define _WIN32_WINNT 0x0501 #include <boost/asio/io_service.hpp> #include <boost/asio/ip/udp.hpp> #include <boost/asio/buffer.hpp> #include <boost/thread.hpp> #include <boost/system/error_code.hpp> #include <boost/bind.hpp> using boost::asio::ip::udp; boost::asio::io_service io_service; //so bleibt der Eventprozessor aktiv, auch wenn nichts zu tun ist boost::asio::io_service::work worker(io_service); std::size_t bufferSize = 64; std::vector<char> buffer ( bufferSize ); std::vector<char> send_buffer ( bufferSize ); boost::asio::ip::udp::socket socket_(io_service); boost::asio::ip::udp::endpoint remote_endpoint ; //muss nicht geheapt werden boost::thread run_thread; void initSocket(); void closeSocket(); void startServer(); void nextCycle(); void handleReceive(boost::system::error_code const & error, std::size_t bytesReceived); void handleSend(boost::system::error_code const & error, std::size_t bytesReceived); void handleError(boost::system::error_code const & error); void restart(std::size_t size); //socket initialisieren void initSocket() { socket_.open (udp::v4()); socket_.bind (udp::endpoint(udp::v4(), 33333)); } //socket schliessen void closeSocket() { socket_.shutdown(udp::socket::shutdown_both); socket_.close(); } //asynchrones Zeugs anwerfen void startServer() { initSocket(); nextCycle(); } //ein Zyklus besteht aus receive->send->... //nextCycle() leitet so einen Zyklus ein void nextCycle() { socket_.async_receive_from ( boost::asio::buffer(buffer) , remote_endpoint , &handleReceive ); } void handleReceive(boost::system::error_code const & error, std::size_t bytesReceived) { if(error) { //bei einem Fehler wollen wir was tun! handleError(error); } else { char const answer[] = "tag"; send_buffer.assign(answer, answer + sizeof(answer)); socket_.async_send_to ( boost::asio::buffer(send_buffer) , remote_endpoint , &handleSend ); } } void handleSend(boost::system::error_code const & error, std::size_t bytesReceived) { if(error) { //bei einem Fehler wollen wir was tun! handleError(error); } else { nextCycle(); } } void handleError(boost::system::error_code const & error) { //hier ist einer der Handler sicher mit einem Fehler //zurueckgekommen std::cerr << "Error: " << error.message() << '\n'; //wenn der Fehlercode "abbruch" sagt (close()): if(error == boost::asio::error::operation_aborted) { //Buffer setzen buffer.assign(bufferSize, 0); //Socket neu oeffnen initSocket(); //neuen Zyklus einleiten nextCycle(); } } void restart(std::size_t size) { bufferSize = size; //Socket schliessen socket_.get_io_service().post(&closeSocket); } int main () { startServer(); run_thread.swap(boost::thread(boost::bind(&boost::asio::io_service::run, &io_service))); for (int i = 0; i < 4; ++i) { std::cout << "server\n"; for (;;) { std::string c; std::cin >> c; if ( c == "quit" ) break; } restart ( 64 ); } }
-
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