From: Leandro Lucarella Date: Sun, 23 Nov 2003 05:07:37 +0000 (+0000) Subject: Varios cambios: X-Git-Tag: svn_import~202 X-Git-Url: https://git.llucax.com/z.facultad/75.42/plaqui.git/commitdiff_plain/212f9ae5dc8899bab8b23ed13d81c28c510db3c3?ds=inline Varios cambios: - Se empiezan a emprolijar las cosas, empezando por Runnable: * Se ponen atributos y signals como privados y se agrega mutex. * El thread que usa ahora no es joinable, por lo que finish() ahora no lleva argumentos. - Se arreglan todas las otras clases (y el programa principal) para que anden con el nuevo Runnable (haciendo loops de espera cuando deben 'joinear' un thread). - Se actuliza el plaqui-client y se le arreglan un par de bugs (ya anda la opcion desconectar del menu). - Se implementa el comando /server/stop por completo (usando una conexion suicida para salir del accept()). - Se agregan separadores de tipos, constantes, atributos y metodos mas llamativos :) --- diff --git a/Client/src/principal.cpp b/Client/src/principal.cpp index 0b59c0b..1b42b2b 100644 --- a/Client/src/principal.cpp +++ b/Client/src/principal.cpp @@ -62,8 +62,13 @@ Principal::Principal(BaseObjectType *co, const Glib::RefPtr & Principal::~Principal() { - if (conexion != NULL) - delete conexion; + if (conexion) { + conexion->finish(); + } + // Espera a que termine realmente. + while (conexion) { + Glib::usleep(10000); // 10 milisegundos + } } void Principal::on_dlg_connect_ok() @@ -75,8 +80,9 @@ void Principal::on_dlg_connect_ok() } catch (...) { txt_view->get_buffer()->insert_at_cursor("NO SE PUDO CREAR OBJETO\n"); - delete conexion; - conexion == NULL; + //delete conexion; XXX Si no me equivoco, si falla el + //constructor, no se reserva la memoria (el delete no va). + conexion = NULL; return; } @@ -122,7 +128,7 @@ void Principal::on_mnu_file_disconnect() PlaQui::Server::Command c("connection", "stop"); c.add_arg(conexion->get_host()); - c.add_arg("7522"); + c.add_arg(conexion->get_port()); conexion->send(c); } diff --git a/Server/include/plaqui/server/command.h b/Server/include/plaqui/server/command.h index 0074557..6f78b53 100644 --- a/Server/include/plaqui/server/command.h +++ b/Server/include/plaqui/server/command.h @@ -43,6 +43,7 @@ namespace Server { /// Pedido HTTP. class Command: private HTTPRequest { + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -50,6 +51,7 @@ namespace Server { /// Tipo de métodos HTTP reconocidos. typedef std::vector Arguments; + ///////////////////////////////////////////////////////////////////// // Atributos. private: @@ -63,6 +65,7 @@ namespace Server { /// Lista de argumentos que recibe el comando. Arguments args; + ///////////////////////////////////////////////////////////////////// // Métodos. private: diff --git a/Server/include/plaqui/server/connection.h b/Server/include/plaqui/server/connection.h index 1eab7fa..7eda172 100644 --- a/Server/include/plaqui/server/connection.h +++ b/Server/include/plaqui/server/connection.h @@ -38,6 +38,7 @@ namespace Server { /// Conexión. class Connection: public Runnable { + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -45,6 +46,7 @@ namespace Server { /// Puerto. typedef unsigned Port; + ///////////////////////////////////////////////////////////////////// // Atributos. protected: @@ -61,6 +63,7 @@ namespace Server { /// Mutex para el socket. //Glib::Mutex socket_mutex; + ///////////////////////////////////////////////////////////////////// // Métodos. public: @@ -98,13 +101,10 @@ namespace Server { /** * Finaliza la conexión. * - * \param attach Si es true, la función no retorna hasta que no - * finalice la tearea (no recomendable). - * * \note Para saber cuando la tarea fue finalizada puede utilizar * la señal signal_finished(). */ - virtual void finish(bool attach = false); + virtual void finish(void); /** * Obtiene el nombre del host local de la conexión. diff --git a/Server/include/plaqui/server/controlclient.h b/Server/include/plaqui/server/controlclient.h index d046c8f..254f815 100644 --- a/Server/include/plaqui/server/controlclient.h +++ b/Server/include/plaqui/server/controlclient.h @@ -40,6 +40,7 @@ namespace Server { /// Conexión para enviar comandos de control a una planta. class ControlClient: public Connection { + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -53,6 +54,7 @@ namespace Server { /// Tipo de señal para indicar que se recibió un error. typedef SigC::Signal1 SignalErrorReceived; + ///////////////////////////////////////////////////////////////////// // Atributos. protected: @@ -69,6 +71,7 @@ namespace Server { /// Receptor del estado de la planta TODO Temporal. Receiver* receiver; + ///////////////////////////////////////////////////////////////////// // Métodos. private: diff --git a/Server/include/plaqui/server/controlserver.h b/Server/include/plaqui/server/controlserver.h index 25d1224..a5cb0fe 100644 --- a/Server/include/plaqui/server/controlserver.h +++ b/Server/include/plaqui/server/controlserver.h @@ -41,7 +41,7 @@ namespace Server { /// Conexión para recibir comandos de control para una planta. class ControlServer: public Connection { - + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -49,7 +49,7 @@ namespace Server { /// Tipo de señal para indicar que se recibió un comando. typedef SigC::Signal1 SignalCommandReceived; - + ///////////////////////////////////////////////////////////////////// // Atributos. private: @@ -57,7 +57,7 @@ namespace Server { /// Señal para indicar que se recibió un comando. SignalCommandReceived command_received; - + ///////////////////////////////////////////////////////////////////// // Métodos. protected: diff --git a/Server/include/plaqui/server/httperror.h b/Server/include/plaqui/server/httperror.h index 1cc4ee8..e55bf61 100644 --- a/Server/include/plaqui/server/httperror.h +++ b/Server/include/plaqui/server/httperror.h @@ -40,6 +40,7 @@ namespace Server { /// Error HTTP. class HTTPError: public std::runtime_error { + ///////////////////////////////////////////////////////////////////// // Atributos. public: @@ -47,6 +48,7 @@ namespace Server { /// Código de error. unsigned code; + ///////////////////////////////////////////////////////////////////// // Métodos. public: diff --git a/Server/include/plaqui/server/httpheaders.h b/Server/include/plaqui/server/httpheaders.h index 23470f3..ce703b2 100644 --- a/Server/include/plaqui/server/httpheaders.h +++ b/Server/include/plaqui/server/httpheaders.h @@ -42,6 +42,7 @@ namespace Server { /// Cabeceras HTTP. class HTTPHeaders: public std::map { + ///////////////////////////////////////////////////////////////////// // Métodos. public: diff --git a/Server/include/plaqui/server/httpmessage.h b/Server/include/plaqui/server/httpmessage.h index 30bc794..37c0287 100644 --- a/Server/include/plaqui/server/httpmessage.h +++ b/Server/include/plaqui/server/httpmessage.h @@ -38,6 +38,7 @@ namespace Server { /// Pedido HTTP. class HTTPMessage { + ///////////////////////////////////////////////////////////////////// // Constantes. public: @@ -52,6 +53,7 @@ namespace Server { static const unsigned NOT_IMPLEMENTED = 501; static const unsigned HTTP_VERSION_NOT_SUPPORTED = 505; + ///////////////////////////////////////////////////////////////////// // Atributos. private: @@ -67,6 +69,7 @@ namespace Server { /// Cabeceras HTTP. HTTPHeaders headers; + ///////////////////////////////////////////////////////////////////// // Métodos. public: diff --git a/Server/include/plaqui/server/httprequest.h b/Server/include/plaqui/server/httprequest.h index 5f0757e..7b43f67 100644 --- a/Server/include/plaqui/server/httprequest.h +++ b/Server/include/plaqui/server/httprequest.h @@ -42,6 +42,7 @@ namespace Server { /// Pedido HTTP. class HTTPRequest: public HTTPMessage { + ///////////////////////////////////////////////////////////////////// // Constantes. protected: @@ -73,6 +74,7 @@ namespace Server { /// Caracteres no hexa para URIs (RFC 2396). static const std::string CHARS_HEX; + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -80,6 +82,7 @@ namespace Server { /// Tipo de métodos HTTP reconocidos. typedef enum {GET, POST} HTTPMethod; + ///////////////////////////////////////////////////////////////////// // Atributos. protected: // TODO hacer privados con get() y set() ??? @@ -96,6 +99,7 @@ namespace Server { /// Query string. std::string query; + ///////////////////////////////////////////////////////////////////// // Métodos. public: diff --git a/Server/include/plaqui/server/httpresponse.h b/Server/include/plaqui/server/httpresponse.h index 5aa8f62..09ff21d 100644 --- a/Server/include/plaqui/server/httpresponse.h +++ b/Server/include/plaqui/server/httpresponse.h @@ -40,6 +40,7 @@ namespace Server { /// Respuesta HTTP. class HTTPResponse: public HTTPMessage { + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -51,6 +52,7 @@ namespace Server { MISSING_HTTP_RESPONSE_CODE } Error; + ///////////////////////////////////////////////////////////////////// // Atributos. //protected: FIXME - hacer privado con get/set? @@ -62,6 +64,7 @@ namespace Server { /// Descripción del código (razón). std::string reason; + ///////////////////////////////////////////////////////////////////// // Métodos. public: diff --git a/Server/include/plaqui/server/plant.h b/Server/include/plaqui/server/plant.h index 31aea96..753899b 100644 --- a/Server/include/plaqui/server/plant.h +++ b/Server/include/plaqui/server/plant.h @@ -40,7 +40,7 @@ namespace Server { /// Planta Química. class Plant: public Runnable { - + ///////////////////////////////////////////////////////////////////// // Tipos. private: @@ -48,7 +48,7 @@ namespace Server { /// Lista de conexiones de control. typedef std::list TransmitterList; - + ///////////////////////////////////////////////////////////////////// // Atributos. private: @@ -68,7 +68,7 @@ namespace Server { /// Nombre del archivo donde esta el XML de la planta. std::string filename; - + ///////////////////////////////////////////////////////////////////// // Métodos. protected: diff --git a/Server/include/plaqui/server/receiver.h b/Server/include/plaqui/server/receiver.h index 462c739..c33fd28 100644 --- a/Server/include/plaqui/server/receiver.h +++ b/Server/include/plaqui/server/receiver.h @@ -40,6 +40,7 @@ namespace Server { /// Conexión para recibir el estado de una planta. class Receiver: public Connection { + ///////////////////////////////////////////////////////////////////// // Constantes. private: @@ -50,7 +51,7 @@ namespace Server { /// Marca de fin de frame. static const std::string FRAME_END; - + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -66,7 +67,7 @@ namespace Server { /// Señal que indica que se recibió un cuadro. SignalFrameReceived frame_received; - + ///////////////////////////////////////////////////////////////////// // Métodos. private: diff --git a/Server/include/plaqui/server/runnable.h b/Server/include/plaqui/server/runnable.h index c46cf8c..258cd2d 100644 --- a/Server/include/plaqui/server/runnable.h +++ b/Server/include/plaqui/server/runnable.h @@ -38,6 +38,7 @@ namespace Server { /// ealizauna tarea (generalmente en un thread). class Runnable { + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -51,28 +52,27 @@ namespace Server { /// Tipo de señal para indicar que hubo un error. typedef SigC::Signal2 SignalError; + ///////////////////////////////////////////////////////////////////// // Atributos. private: /// Thread en el cual correr la tarea. - Glib::Thread* thread; + Glib::Thread* _thread; /// Señal que indica que se finalizó la tarea. - SignalFinished finished; - - protected: + SignalFinished _finished; /// Señal que indica que hubo un error. - SignalError error; + SignalError _error; - /** - * Indica si se debe frinalizar la tarea. - * - * \todo Poner como privado y poner get() set() con locks. - */ - bool stop; + /// Indica si se debe frinalizar la tarea. + bool _stop; + /// Mutex para stop. + Glib::Mutex stop_mutex; + + ///////////////////////////////////////////////////////////////////// // Métodos. private: @@ -86,7 +86,23 @@ namespace Server { protected: - /// Realiza la terea. + /** + * Indica si la tarea debe finalizar. + */ + bool stop(void); + + /** + * Establece si la tarea debe finalizar. + * + * \param stop Nuevo valor. + * + * \return Valor anterior. + */ + bool stop(bool stop); + + /** + * Realiza la terea. + */ virtual void real_run(void) = 0; public: @@ -112,13 +128,10 @@ namespace Server { /** * Finaliza la tarea. * - * \param attach Si es true, la función no retorna hasta que no - * finalice la tearea (no recomendable). - * * \note Para saber cuando la tarea fue finalizada puede utilizar * la señal signal_finished(). */ - virtual void finish(bool attach = false); + virtual void finish(void); /** * Obtiene la señal que avisa cuando la tarea es finalizada. diff --git a/Server/include/plaqui/server/server.h b/Server/include/plaqui/server/server.h index ae83251..f8757e7 100644 --- a/Server/include/plaqui/server/server.h +++ b/Server/include/plaqui/server/server.h @@ -47,6 +47,7 @@ namespace Server { */ class Server: public TCPServer { + ///////////////////////////////////////////////////////////////////// // Tipos. private: @@ -54,6 +55,7 @@ namespace Server { /// Lista de plantas químicas. typedef std::map PlantList; + ///////////////////////////////////////////////////////////////////// // Atributos. private: @@ -64,6 +66,7 @@ namespace Server { /// Mutex para las plantas. Glib::Mutex plants_mutex; + ///////////////////////////////////////////////////////////////////// // Métodos. protected: diff --git a/Server/include/plaqui/server/string.h b/Server/include/plaqui/server/string.h index 96e2bb8..9c0d72a 100644 --- a/Server/include/plaqui/server/string.h +++ b/Server/include/plaqui/server/string.h @@ -51,9 +51,12 @@ namespace Server { return p2; } - /// Conexión. + /// String con varios métodos útiles. class String: public std::string { + ///////////////////////////////////////////////////////////////////// + // Métodos. + public: /// Caracteres que son considerados espacios a la hora de parsear. diff --git a/Server/include/plaqui/server/tcpserver.h b/Server/include/plaqui/server/tcpserver.h index a64b545..d94918e 100644 --- a/Server/include/plaqui/server/tcpserver.h +++ b/Server/include/plaqui/server/tcpserver.h @@ -44,6 +44,7 @@ namespace Server { */ class TCPServer: public Runnable { + ///////////////////////////////////////////////////////////////////// // Constantes. private: @@ -51,6 +52,7 @@ namespace Server { /// Cantidad máxima de conexiones pendientes. static const unsigned MAX_PENDING_CONNECTIONS = 10; + ///////////////////////////////////////////////////////////////////// // Tipos. private: @@ -71,12 +73,14 @@ namespace Server { /// Lista de información de conexiones de control. typedef std::vector ConnectionInfoList; + ///////////////////////////////////////////////////////////////////// // Atributos. - private: + protected: //FIXME /// Socket para escuchar conexiones. sockinetbuf socket; + private: // FIXME /// Conexiones de control. ConnectionList connections; @@ -84,6 +88,7 @@ namespace Server { /// Mutex para las conexiones. Glib::Mutex connections_mutex; + ///////////////////////////////////////////////////////////////////// // Métodos. private: @@ -121,13 +126,10 @@ namespace Server { /** * Finaliza la tarea. * - * \param attach Si es true, la función no retorna hasta que no - * finalice la tearea (no recomendable). - * * \note Para saber cuando la tarea fue finalizada puede utilizar * la señal signal_finished(). */ - //virtual void finish(bool attach = false); + //virtual void finish(void); /** * Se encarga de borrar una conexión de la lista cuando finaliza. diff --git a/Server/include/plaqui/server/transmitter.h b/Server/include/plaqui/server/transmitter.h index acf38e8..624ff3b 100644 --- a/Server/include/plaqui/server/transmitter.h +++ b/Server/include/plaqui/server/transmitter.h @@ -38,6 +38,7 @@ namespace Server { /// Conexión para transmitir el estado de una planta. class Transmitter: public Connection { + ///////////////////////////////////////////////////////////////////// // Métodos. private: diff --git a/Server/src/connection.cpp b/Server/src/connection.cpp index 75915c9..c355c86 100644 --- a/Server/src/connection.cpp +++ b/Server/src/connection.cpp @@ -74,19 +74,21 @@ Connection::Connection(const std::string& host, const Port& port): #endif // DEBUG } -void Connection::finish(bool attach) { +void Connection::finish(void) { #ifdef DEBUG cerr << __FILE__ << "(" << __LINE__ << ")" - << ": finish(attach = " << attach << ")." << endl; + << ": finish();" << endl; #endif // DEBUG //socket_mutex.lock(); try { socket->shutdown(sockbuf::shut_readwrite); + // FIXME socket->close(sockbuf::shut_readwrite); + // close(socket->sd()); } catch (const sockerr& e) { - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); } //socket_mutex.unlock(); - Runnable::finish(attach); + Runnable::finish(); } const string& Connection::get_host(void) const { diff --git a/Server/src/controlclient.cpp b/Server/src/controlclient.cpp index 75e330b..653fcae 100644 --- a/Server/src/controlclient.cpp +++ b/Server/src/controlclient.cpp @@ -43,7 +43,9 @@ ControlClient::~ControlClient(void) { << ": destructor." << endl; #endif // DEBUG // TODO Temporal: espero que el receiver muera. - receiver->finish(true); + // Conectar señal on_receiver_finished() y esperar a que el puntero sea + // NULL para saber que terminó. + receiver->finish(); } ControlClient::ControlClient(const string& _host, @@ -75,14 +77,14 @@ void ControlClient::real_run(void) { try { } catch (const sockerr& e) { // TODO Poner una señal de error específica? - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); return; } // TODO sacar signal_connected? connected(); // TODO Temporal: el receiver empieza a escuchar. receiver->run(); - while (!stop) { + while (!stop()) { HTTPResponse response; try { //Glib::Mutex::Lock lock(socket_mutex); @@ -90,10 +92,10 @@ void ControlClient::real_run(void) { // Si se cerró el socket. } catch (const ios::failure& e) { // TODO poner buenos codigos de error. - error(1000000, "Se desconectó."); + signal_error().emit(1000000, "Se desconectó."); return; } catch (const sockerr& e) { - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); return; // Si hay un error al parsear la respuesta. } catch (const HTTPResponse::Error& e) { @@ -120,7 +122,7 @@ void ControlClient::send(const Command& command) { try { socket << command << flush; } catch (const sockerr& e) { - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); finish(); } #ifdef DEBUG diff --git a/Server/src/controlserver.cpp b/Server/src/controlserver.cpp index a9cf729..41d5419 100644 --- a/Server/src/controlserver.cpp +++ b/Server/src/controlserver.cpp @@ -63,17 +63,17 @@ void ControlServer::real_run(void) { << ": real_run()" << endl; #endif // DEBUG //char buf[BUFSIZ]; - while (!stop) { + while (!stop()) { Command command; try { //Glib::Mutex::Lock lock(socket_mutex); socket >> command; } catch (const ios::failure& e) { // TODO poner buenos codigos de error. - error(1000000, "Se desconectó."); + signal_error().emit(1000000, "Se desconectó."); return; } catch (const sockerr& e) { - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); return; // Si se cerró el socket. //} catch (const ios::failure& e) { diff --git a/Server/src/main.cpp b/Server/src/main.cpp index 7ac8ff4..08c7cd5 100644 --- a/Server/src/main.cpp +++ b/Server/src/main.cpp @@ -82,6 +82,10 @@ int main(int argc, char* argv[]) { } catch (const sockerr& e) { cerr << "Socket Error: " << e.operation() << " | serrno = " << e.serrno() << " | errstr = " << e.errstr() << endl; + if (e.serrno() == 98) { + cerr << "No se puede usar el puerto " << port << " porque ya está " + "siendo utilizado por otro programa." << endl; + } if (e.io()) { cerr << "Es: non-blocking and interrupt io recoverable error." << endl; @@ -112,16 +116,23 @@ int main(int argc, char* argv[]) { // Conecto señal para atender errores. server->signal_error().connect(SigC::slot(on_error)); + // Conecto señal para atender la finalización del server. + server->signal_finished().connect(SigC::slot(on_finished)); + // Corre el server. - server->run(false); + server->run(); // Espera a que el server se muera. while (server) { - Glib::usleep(1000000); + //cerr << "-----------------\n\nAHHHHHHH\n\n----------------" << endl; + Glib::usleep(100000); // 0,1 segundos } + // Espera un segundo más por las dudas, para asegurarse de que terminó. + Glib::usleep(1000000); // 1 segundo // Como no detachee el server, lo tengo que eliminar a mano. //delete server; return 0; } + diff --git a/Server/src/plant.cpp b/Server/src/plant.cpp index b020e21..0e70a1f 100644 --- a/Server/src/plant.cpp +++ b/Server/src/plant.cpp @@ -44,11 +44,20 @@ Plant::~Plant(void) { cerr << __FILE__ << "(" << __LINE__ << ")" << ": destructor." << endl; #endif // DEBUG - // Termino transmisiones. - Glib::Mutex::Lock lock(transmissions_mutex); - for (TransmitterList::iterator trans = transmissions.end(); + // Mando a terminar todas las transmisiones. + transmissions_mutex.lock(); + for (TransmitterList::iterator trans = transmissions.begin(); trans != transmissions.end(); trans++) { - (*trans)->finish(true); + (*trans)->finish(); + } + TransmitterList::size_type count = transmissions.size(); + transmissions_mutex.unlock(); + // Espero que terminen realmente. + while (count) { + Glib::usleep(10000); // 10 milisegundos + transmissions_mutex.lock(); + count = transmissions.size(); + transmissions_mutex.unlock(); } } @@ -76,7 +85,7 @@ void Plant::real_run(void) { cerr << __FILE__ << "(" << __LINE__ << ")" << ": real_run." << endl; #endif // DEBUG - while (!stop) { + while (!stop()) { simulator_mutex.lock(); simulator.simulate(); string plantstatus = simulator.get_state_as_xml(); @@ -87,7 +96,7 @@ void Plant::real_run(void) { (*i)->send(plantstatus); } transmissions_mutex.unlock(); - Glib::usleep(1000000); + Glib::usleep(100000); } } diff --git a/Server/src/receiver.cpp b/Server/src/receiver.cpp index 22cc1a8..6e6c503 100644 --- a/Server/src/receiver.cpp +++ b/Server/src/receiver.cpp @@ -68,13 +68,13 @@ void Receiver::real_run(void) { char buf[BUFSIZ]; bool in_frame = false; stringstream ss; - while (!stop) { + while (!stop()) { try { if (!socket.getline(buf, BUFSIZ)) { return; // Se terminó la transmision. } } catch (const sockerr& e) { - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); return; } string sbuf = buf; diff --git a/Server/src/runnable.cpp b/Server/src/runnable.cpp index d9d5048..7079143 100644 --- a/Server/src/runnable.cpp +++ b/Server/src/runnable.cpp @@ -46,7 +46,7 @@ Runnable::~Runnable(void) { #endif // DEBUG } -Runnable::Runnable(void): thread(0), stop(false) { +Runnable::Runnable(void): _thread(NULL), _stop(false) { #ifdef DEBUG cerr << __FILE__ << "(" << __LINE__ << ")" << ": constructor." << endl; @@ -56,12 +56,10 @@ Runnable::Runnable(void): thread(0), stop(false) { void Runnable::static_run(Runnable* runner) { #ifdef DEBUG cerr << __FILE__ << "(" << __LINE__ << ")" - << ": static_run(runner = " << runner << ")" - << endl; + << ": static_run(runner = " << runner << ")" << endl; #endif // DEBUG runner->real_run(); - runner->finished(); - //runner->thread->join(); + runner->_finished(); delete runner; } @@ -74,9 +72,9 @@ void Runnable::run(bool detach) { if (detach) { // Corremos el thread en una funcion estática para poder destruirlo al // finalizar, pasandole el puntero al objeto. - thread = Glib::Thread::create( + _thread = Glib::Thread::create( SigC::bind(SigC::slot(&Runnable::static_run), this), - true);//false); + false);//true); // Si no corremos la tarea normalmente. } else { real_run(); @@ -84,23 +82,33 @@ void Runnable::run(bool detach) { } -void Runnable::finish(bool attach) { +void Runnable::finish(void) { #ifdef DEBUG cerr << __FILE__ << "(" << __LINE__ << ")" - << ": finish(attach = " << attach << ")" << endl; + << ": finish();" << endl; #endif // DEBUG - stop = true; - if (attach) { - thread->join(); - } + stop(true); +} + +bool Runnable::stop(void) { + Glib::Mutex::Lock lock(stop_mutex); + bool tmp = _stop; + return tmp; +} + +bool Runnable::stop(bool stop) { + Glib::Mutex::Lock lock(stop_mutex); + bool tmp = _stop; + _stop = stop; + return tmp; } Runnable::SignalFinished& Runnable::signal_finished(void) { - return finished; + return _finished; } Runnable::SignalError& Runnable::signal_error(void) { - return error; + return _error; } } // namespace Server diff --git a/Server/src/server.cpp b/Server/src/server.cpp index 340c2f0..e332866 100644 --- a/Server/src/server.cpp +++ b/Server/src/server.cpp @@ -29,6 +29,7 @@ #include "plaqui/server/connection.h" #include "plaqui/server/controlserver.h" #include +#include #include #include #ifdef DEBUG @@ -47,10 +48,19 @@ Server::~Server(void) { cerr << __FILE__ << "(" << __LINE__ << ")" << ": destructor." << endl; #endif // DEBUG - // Termino plantas. - Glib::Mutex::Lock lock(plants_mutex); - for (PlantList::iterator i = plants.end(); i != plants.end(); i++) { - i->second->finish(true); + // Mando a terminar todas las plantas. + plants_mutex.lock(); + for (PlantList::iterator i = plants.begin(); i != plants.end(); i++) { + i->second->finish(); + } + PlantList::size_type count = plants.size(); + plants_mutex.unlock(); + // Espero que terminen realmente. + while (count) { + Glib::usleep(10000); // 10 milisegundos + plants_mutex.lock(); + count = plants.size(); + plants_mutex.unlock(); } } @@ -60,7 +70,7 @@ Server::Server(const string& plant_filename, const Connection::Port& port) cerr << __FILE__ << "(" << __LINE__ << ")" << ": port = " << port << endl; #endif // DEBUG - // FIXME + // FIXME - hacer que se puedan cargar mas plantas bien. Glib::Mutex::Lock lock(plants_mutex); plants["default"] = new Plant(plant_filename); plants["default"]->signal_finished().connect( @@ -114,6 +124,19 @@ void Server::on_control_command_received(const Command& command, finish(); response = new HTTPResponse(HTTPMessage::OK, ""); + response->headers["Content-Type"] = "text/xml; charset=iso-8859-1"; + controlserver->send(*response); + delete response; + // Creo una conexión suicida para que el accept() del server retorne + // el control y el server pueda terminar realmente. + try { + sockinetbuf suicida(sockbuf::sock_stream); + suicida.connect(socket.localhost(), socket.localport()); + } catch (...) { + // FIXME + signal_error().emit(12345, "ahhhh! no puedo crear conexion suicida"); + } + return; } else { response = new HTTPResponse(HTTPMessage::NOT_FOUND, ""); diff --git a/Server/src/tcpserver.cpp b/Server/src/tcpserver.cpp index ffbdead..8272e57 100644 --- a/Server/src/tcpserver.cpp +++ b/Server/src/tcpserver.cpp @@ -27,6 +27,7 @@ #include "plaqui/server/tcpserver.h" #include +#include #ifdef DEBUG # include #endif // DEBUG @@ -42,10 +43,20 @@ TCPServer::~TCPServer(void) { cerr << __FILE__ << "(" << __LINE__ << ")" << ": destructor." << endl; #endif // DEBUG - Glib::Mutex::Lock lock(connections_mutex); + // Mando a terminar todas las conexiones. + connections_mutex.lock(); for (ConnectionList::iterator con = connections.begin(); con != connections.end(); con++) { - (*con)->finish(true); + (*con)->finish(); + } + ConnectionList::size_type count = connections.size(); + connections_mutex.unlock(); + // Espero que terminen realmente. + while (count) { + Glib::usleep(10000); // 10 milisegundos + connections_mutex.lock(); + count = connections.size(); + connections_mutex.unlock(); } } @@ -75,8 +86,13 @@ TCPServer::TCPServer(const Connection::Port& port) throw(sockerr): } /*void TCPServer::finish(bool attach) { +#ifdef DEBUG + cerr << __FILE__ << "(" << __LINE__ << ")" + << ": finish(attach = " << attach << ");" << endl; +#endif // DEBUG //socket_mutex.lock(); - socket.shutdown(sockbuf::shut_readwrite); + close(socket.sd()); + //socket.shutdown(sockbuf::shut_readwrite); //socket_mutex.unlock(); Runnable::finish(attach); }*/ @@ -106,12 +122,12 @@ void TCPServer::real_run(void) { << ": real_run()" << endl; #endif // DEBUG Connection* connection; - while (!stop) { + while (!stop()) { // Forma grasa de salir del accept: crear conexion que salga al toque. try { connection = new_connection(socket.accept()); } catch (const sockerr& e) { // No se si el accept() puede fallar. - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); continue; // Supongo que puede seguir aceptando conexiones. } #ifdef DEBUG diff --git a/Server/src/transmitter.cpp b/Server/src/transmitter.cpp index 6ab9260..4348da6 100644 --- a/Server/src/transmitter.cpp +++ b/Server/src/transmitter.cpp @@ -71,7 +71,7 @@ void Transmitter::real_run(void) { << ": real_run()." << endl; #endif // DEBUG // No hace nada, porque solo actua cuando se manda algo con send(). - while (!stop) { + while (!stop()) { Glib::usleep(500000); // 1/2 segundo } } @@ -82,14 +82,14 @@ void Transmitter::send(const string& data) { << ": send()." << endl; // << ": send(data = " << data << ")." << endl; #endif // DEBUG - if (stop) { + if (stop()) { return; } try { socket << data << flush; } catch (const sockerr& e) { - error(e.serrno(), e.errstr()); - stop = true; + signal_error().emit(e.serrno(), e.errstr()); + stop(true); } } diff --git a/docs/cliente_servidor.dia b/docs/cliente_servidor.dia index cad9d44..1869c18 100644 Binary files a/docs/cliente_servidor.dia and b/docs/cliente_servidor.dia differ