Thread: [Cppcms-users] SSE keep-alive
Brought to you by:
artyom-beilis
|
From: Christian G. <chr...@gm...> - 2013-04-01 18:37:51
|
HI all, I am trying to understand the keep-alive mechanism used in the SSE classes. I have the following problem: For test purposes I lowered the http timeout to 10 seconds, see keep-live is set to 1 second and the session timeout is set to 20 seconds. Now a client opens the sse stream /sse/get and gets a "ping" message. Now in theory every second the see keep-alive worker should do its work, but it looks like long_pollers_ and streamers_ are empty. void event_source::keep_alive(char const *comment) gets called every seconds but as long_pollers_ and streamers are empty no keep alive is send. There are two places where streamers_.insert is called: class post_send and void event_source::accept(booster::shared_ptr<cppcms::http::context> ctx). Maybe somebody can help me to under stand it! thanks -- Christian Gmeiner, MSc |
|
From: Artyom B. <art...@ya...> - 2013-04-01 20:16:18
|
----- Original Message ----- > From: Christian Gmeiner <chr...@gm...> > To: cpp...@li... > Cc: > Sent: Monday, April 1, 2013 9:37 PM > Subject: [Cppcms-users] SSE keep-alive > > HI all, > > I am trying to understand the keep-alive mechanism used in the SSE > classes. I have the following problem: > > For test purposes I lowered the http timeout to 10 seconds, see > keep-live is set to 1 second and the session timeout is set to 20 > seconds. > Now a client opens the sse stream /sse/get and gets a "ping" message. > Now in theory every second the see keep-alive worker should do its > work, but it > looks like long_pollers_ and streamers_ are empty. void > event_source::keep_alive(char const *comment) gets called every > seconds but as long_pollers_ > and streamers are empty no keep alive is send. > There are two places where streamers_.insert is called: class > post_send and void > event_source::accept(booster::shared_ptr<cppcms::http::context> ctx). > > Maybe somebody can help me to under stand it! > > thanks > -- > Christian Gmeiner, MSc > I don't really understand your setup. Does a user connected to the thread get the keep alive messages (empty comment messages like :keep-alive) or not? In general SSE has "comment" messages that are not dispatched but rather used for Keep alive to let the browser know that the server had not gone and the server to know that the client is alive (on TCP/IP level) Artyom Beilis -------------- CppCMS - C++ Web Framework: http://cppcms.com/ CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/ |
|
From: Christian G. <chr...@gm...> - 2013-04-02 07:43:44
|
2013/4/1 Artyom Beilis <art...@ya...>: > > > ----- Original Message ----- >> From: Christian Gmeiner <chr...@gm...> >> To: cpp...@li... >> Cc: >> Sent: Monday, April 1, 2013 9:37 PM >> Subject: [Cppcms-users] SSE keep-alive >> >> HI all, >> >> I am trying to understand the keep-alive mechanism used in the SSE >> classes. I have the following problem: >> >> For test purposes I lowered the http timeout to 10 seconds, see >> keep-live is set to 1 second and the session timeout is set to 20 >> seconds. >> Now a client opens the sse stream /sse/get and gets a "ping" message. >> Now in theory every second the see keep-alive worker should do its >> work, but it >> looks like long_pollers_ and streamers_ are empty. void >> event_source::keep_alive(char const *comment) gets called every >> seconds but as long_pollers_ >> and streamers are empty no keep alive is send. >> There are two places where streamers_.insert is called: class >> post_send and void >> event_source::accept(booster::shared_ptr<cppcms::http::context> ctx). >> >> Maybe somebody can help me to under stand it! >> >> thanks >> -- >> Christian Gmeiner, MSc >> > > > > I don't really understand your setup. Does a user connected to the > thread get the keep alive messages (empty comment messages like :keep-alive) > or not? > A user _NEVER_ gets the keep alive message.. thats why I am asking :) I have added some debug to void event_source::keep_alive(char const *comment): http://dpaste.com/hold/1043987/ Here is an example log output: http://dpaste.com/hold/1044005/ As you can see after then last data transfer via SSE the keep_alive gets called, but does nothing. After 5 seconds the connection run into a timeout. My used config: { "service" : { "api" : "http", "ip" : "0.0.0.0", "port" : 8080 }, "http" : { "script" : "/tssw", "timeout" : 5, }, "session" : { "expire" : "renew", "timeout" : 15, "location" : "server", "gc" : 10, "server": { "storage":"memory" } }, "file_server" : { "enable" : true, "document_root" : "/opt/tssw/", "listing" : false, "alias" : [ { "url" : "/assets" , "path" : "/opt/tssw/" }, { "url" : "/downloads" , "path" : "/home/vis/" } ], }, "security" : { "csrf" : { "enable" : true }, "multipart_form_data_limit" : 1048576, "uploads_path" : "/home/vis/" }, "localization" : { "messages" : { "paths" : [ "/opt/tssw/locale" ], "domains" : [ "tssw" ] }, "locales" : [ "en.UTF-8", "de.UTF-8", "zh.UTF-8" ] }, "logging" : { "level" : "debug", "syslog" : { "enable" : true, "id" : "tssw", }, } } My used SSE application looks like: SSE::SSE(cppcms::service &srv) : cppcms::application(srv) { stream_ = sse::event_fifo::create(srv.get_io_service()); stream_->enable_keep_alive(1); dispatcher().assign("/get",&SSE::get,this); } void SSE::get() { stream_->accept(release_context()); } void SSE::enqueue(std::string const &event, std::string const &data) { stream_->push(event, data); } And my used event_fifo class: class event_fifo : public event_source { protected: event_fifo(booster::aio::io_service &srv) : event_source(srv) { } public: /// /// Create a queue of maximal size \a size, such that user that connects too late /// it would be able to receive at most \a size latest messages /// static booster::shared_ptr<event_fifo> create( booster::aio::io_service &srv) { booster::shared_ptr<event_fifo> p(new event_fifo(srv)); return p; } virtual void accept(booster::shared_ptr<cppcms::http::context> ctx) { // remove old messages mutex.lock(); while (messages_.empty() == false) { messages_.pop(); } mutex.unlock(); event_source::accept(ctx); // we need to send something that the EventSource on the client side // gets notified that the stream is open. push("welcome", "welcome"); } /// /// put a message into the fifo /// /// If \a send is false the messages are not dispatched /// immediately, you can dispatch them later by calling broadcast() or by calling push /// event with send=true /// void push(std::string const &data,bool send=true) { push(std::string(),data,send); } /// /// put a message into the fifo /// /// If \a send is false the messages are not dispatched /// immediately, you can dispatch them later by calling broadcast() or by calling push /// event with send=true /// void push(std::string const &event,std::string const &data,bool send=true) { message msg; msg.event = event; msg.data = data; mutex.lock(); messages_.push(msg); mutex.unlock(); if(send) broadcast(); } protected: bool on_sent(event_stream &es) { size_t last_id = es.last_integer_id(); size_t id = last_id; mutex.lock(); while (messages_.empty() == false) { id++; message &msg = messages_.front(); es.write(msg.data, id, msg.event); messages_.pop(); } mutex.unlock(); return true; } private: struct message { std::string event; std::string data; }; std::queue<message> messages_; booster::mutex mutex; }; } // namespace sse Oh... it is planed to have one SSE stream per session. If you need it I can provide you a simple demo application. greets -- Christian Gmeiner, MSc |
|
From: Christian G. <chr...@gm...> - 2013-04-02 11:01:13
|
2013/4/2 Christian Gmeiner <chr...@gm...>: > 2013/4/1 Artyom Beilis <art...@ya...>: >> >> >> ----- Original Message ----- >>> From: Christian Gmeiner <chr...@gm...> >>> To: cpp...@li... >>> Cc: >>> Sent: Monday, April 1, 2013 9:37 PM >>> Subject: [Cppcms-users] SSE keep-alive >>> >>> HI all, >>> >>> I am trying to understand the keep-alive mechanism used in the SSE >>> classes. I have the following problem: >>> >>> For test purposes I lowered the http timeout to 10 seconds, see >>> keep-live is set to 1 second and the session timeout is set to 20 >>> seconds. >>> Now a client opens the sse stream /sse/get and gets a "ping" message. >>> Now in theory every second the see keep-alive worker should do its >>> work, but it >>> looks like long_pollers_ and streamers_ are empty. void >>> event_source::keep_alive(char const *comment) gets called every >>> seconds but as long_pollers_ >>> and streamers are empty no keep alive is send. >>> There are two places where streamers_.insert is called: class >>> post_send and void >>> event_source::accept(booster::shared_ptr<cppcms::http::context> ctx). >>> >>> Maybe somebody can help me to under stand it! >>> >>> thanks >>> -- >>> Christian Gmeiner, MSc >>> >> >> >> >> I don't really understand your setup. Does a user connected to the >> thread get the keep alive messages (empty comment messages like :keep-alive) >> or not? >> > > A user _NEVER_ gets the keep alive message.. thats why I am asking :) > > I have added some debug to void event_source::keep_alive(char const *comment): > http://dpaste.com/hold/1043987/ > > > Here is an example log output: > http://dpaste.com/hold/1044005/ > > > As you can see after then last data transfer via SSE the keep_alive > gets called, but does nothing. > After 5 seconds the connection run into a timeout. > > > My used config: > > { > "service" : { > "api" : "http", > "ip" : "0.0.0.0", > "port" : 8080 > }, > "http" : { > "script" : "/tssw", > "timeout" : 5, > }, > "session" : { > "expire" : "renew", > "timeout" : 15, > "location" : "server", > "gc" : 10, > "server": { > "storage":"memory" > } > }, > "file_server" : { > "enable" : true, > "document_root" : "/opt/tssw/", > "listing" : false, > "alias" : [ > { "url" : "/assets" , "path" : "/opt/tssw/" }, > { "url" : "/downloads" , "path" : "/home/vis/" } > ], > }, > "security" : { > "csrf" : { > "enable" : true > }, > "multipart_form_data_limit" : 1048576, > "uploads_path" : "/home/vis/" > }, > "localization" : { > "messages" : { > "paths" : [ "/opt/tssw/locale" ], > "domains" : [ "tssw" ] > }, > "locales" : [ "en.UTF-8", "de.UTF-8", "zh.UTF-8" ] > }, > "logging" : { > "level" : "debug", > "syslog" : { > "enable" : true, > "id" : "tssw", > }, > } > } > > > My used SSE application looks like: > > SSE::SSE(cppcms::service &srv) : cppcms::application(srv) > { > stream_ = sse::event_fifo::create(srv.get_io_service()); > stream_->enable_keep_alive(1); > > dispatcher().assign("/get",&SSE::get,this); > } > > void SSE::get() > { > stream_->accept(release_context()); > } > > void SSE::enqueue(std::string const &event, std::string const &data) > { > stream_->push(event, data); > } > > > And my used event_fifo class: > > class event_fifo : public event_source { > protected: > event_fifo(booster::aio::io_service &srv) : > event_source(srv) > { > } > public: > /// > /// Create a queue of maximal size \a size, such that user that > connects too late > /// it would be able to receive at most \a size latest messages > /// > static booster::shared_ptr<event_fifo> create( > booster::aio::io_service &srv) > { > booster::shared_ptr<event_fifo> p(new event_fifo(srv)); > return p; > } > > virtual void accept(booster::shared_ptr<cppcms::http::context> ctx) > { > // remove old messages > mutex.lock(); > while (messages_.empty() == false) > { > messages_.pop(); > } > mutex.unlock(); > > event_source::accept(ctx); > > // we need to send something that the EventSource on the client side > // gets notified that the stream is open. > push("welcome", "welcome"); > } > > /// > /// put a message into the fifo > /// > /// If \a send is false the messages are not dispatched > /// immediately, you can dispatch them later by calling > broadcast() or by calling push > /// event with send=true > /// > void push(std::string const &data,bool send=true) > { > push(std::string(),data,send); > } > > /// > /// put a message into the fifo > /// > /// If \a send is false the messages are not dispatched > /// immediately, you can dispatch them later by calling > broadcast() or by calling push > /// event with send=true > /// > void push(std::string const &event,std::string const &data,bool send=true) > { > message msg; > msg.event = event; > msg.data = data; > > mutex.lock(); > messages_.push(msg); > mutex.unlock(); > > if(send) > broadcast(); > } > > protected: > bool on_sent(event_stream &es) > { > size_t last_id = es.last_integer_id(); > size_t id = last_id; > > mutex.lock(); > while (messages_.empty() == false) > { > id++; > message &msg = messages_.front(); > es.write(msg.data, id, msg.event); > messages_.pop(); > } > mutex.unlock(); > > return true; > } > > private: > struct message { > std::string event; > std::string data; > }; > std::queue<message> messages_; > booster::mutex mutex; > }; > > } // namespace sse > > Oh... it is planed to have one SSE stream per session. > If you need it I can provide you a simple demo application. > Finally I got keep_alive working by changing on_send bool on_sent(event_stream &es) { bool something_send = false; size_t last_id = es.last_integer_id(); size_t id = last_id; mutex.lock(); while (messages_.empty() == false) { id++; message &msg = messages_.front(); es.write(msg.data, id, msg.event); messages_.pop(); something_send = true; } mutex.unlock(); return something_send; } Now I am looking to prevent expiration of the user session. greets -- Christian Gmeiner, MSc |
|
From: Artyom B. <art...@ya...> - 2013-04-02 11:26:49
|
I don't really understand why do you have mutex... You may not write to the event stream from a thread that is not the event loop thread. If you want to notify the asynchronous SSE on anything you need to use cppcms::service::post() with a callback that would be executed in the event loop. Artyom Beilis -------------- CppCMS - C++ Web Framework: http://cppcms.com/ CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/ >________________________________ > From: Christian Gmeiner <chr...@gm...> >To: Artyom Beilis <art...@ya...>; cpp...@li... >Sent: Tuesday, April 2, 2013 2:00 PM >Subject: Re: [Cppcms-users] SSE keep-alive > >2013/4/2 Christian Gmeiner <chr...@gm...>: >> 2013/4/1 Artyom Beilis <art...@ya...>: >>> >>> >>> ----- Original Message ----- >>>> From: Christian Gmeiner <chr...@gm...> >>>> To: cpp...@li... >>>> Cc: >>>> Sent: Monday, April 1, 2013 9:37 PM >>>> Subject: [Cppcms-users] SSE keep-alive >>>> >>>> HI all, >>>> >>>> I am trying to understand the keep-alive mechanism used in the SSE >>>> classes. I have the following problem: >>>> >>>> For test purposes I lowered the http timeout to 10 seconds, see >>>> keep-live is set to 1 second and the session timeout is set to 20 >>>> seconds. >>>> Now a client opens the sse stream /sse/get and gets a "ping" message. >>>> Now in theory every second the see keep-alive worker should do its >>>> work, but it >>>> looks like long_pollers_ and streamers_ are empty. void >>>> event_source::keep_alive(char const *comment) gets called every >>>> seconds but as long_pollers_ >>>> and streamers are empty no keep alive is send. >>>> There are two places where streamers_.insert is called: class >>>> post_send and void >>>> event_source::accept(booster::shared_ptr<cppcms::http::context> ctx). >>>> >>>> Maybe somebody can help me to under stand it! >>>> >>>> thanks >>>> -- >>>> Christian Gmeiner, MSc >>>> >>> >>> >>> >>> I don't really understand your setup. Does a user connected to the >>> thread get the keep alive messages (empty comment messages like :keep-alive) >>> or not? >>> >> >> A user _NEVER_ gets the keep alive message.. thats why I am asking :) >> >> I have added some debug to void event_source::keep_alive(char const *comment): >> http://dpaste.com/hold/1043987/ >> >> >> Here is an example log output: >> http://dpaste.com/hold/1044005/ >> >> >> As you can see after then last data transfer via SSE the keep_alive >> gets called, but does nothing. >> After 5 seconds the connection run into a timeout. >> >> >> My used config: >> >> { >> "service" : { >> "api" : "http", >> "ip" : "0.0.0.0", >> "port" : 8080 >> }, >> "http" : { >> "script" : "/tssw", >> "timeout" : 5, >> }, >> "session" : { >> "expire" : "renew", >> "timeout" : 15, >> "location" : "server", >> "gc" : 10, >> "server": { >> "storage":"memory" >> } >> }, >> "file_server" : { >> "enable" : true, >> "document_root" : "/opt/tssw/", >> "listing" : false, >> "alias" : [ >> { "url" : "/assets" , "path" : "/opt/tssw/" }, >> { "url" : "/downloads" , "path" : "/home/vis/" } >> ], >> }, >> "security" : { >> "csrf" : { >> "enable" : true >> }, >> "multipart_form_data_limit" : 1048576, >> "uploads_path" : "/home/vis/" >> }, >> "localization" : { >> "messages" : { >> "paths" : [ "/opt/tssw/locale" ], >> "domains" : [ "tssw" ] >> }, >> "locales" : [ "en.UTF-8", "de.UTF-8", "zh.UTF-8" ] >> }, >> "logging" : { >> "level" : "debug", >> "syslog" : { >> "enable" : true, >> "id" : "tssw", >> }, >> } >> } >> >> >> My used SSE application looks like: >> >> SSE::SSE(cppcms::service &srv) : cppcms::application(srv) >> { >> stream_ = sse::event_fifo::create(srv.get_io_service()); >> stream_->enable_keep_alive(1); >> >> dispatcher().assign("/get",&SSE::get,this); >> } >> >> void SSE::get() >> { >> stream_->accept(release_context()); >> } >> >> void SSE::enqueue(std::string const &event, std::string const &data) >> { >> stream_->push(event, data); >> } >> >> >> And my used event_fifo class: >> >> class event_fifo : public event_source { >> protected: >> event_fifo(booster::aio::io_service &srv) : >> event_source(srv) >> { >> } >> public: >> /// >> /// Create a queue of maximal size \a size, such that user that >> connects too late >> /// it would be able to receive at most \a size latest messages >> /// >> static booster::shared_ptr<event_fifo> create( >> booster::aio::io_service &srv) >> { >> booster::shared_ptr<event_fifo> p(new event_fifo(srv)); >> return p; >> } >> >> virtual void accept(booster::shared_ptr<cppcms::http::context> ctx) >> { >> // remove old messages >> mutex.lock(); >> while (messages_.empty() == false) >> { >> messages_.pop(); >> } >> mutex.unlock(); >> >> event_source::accept(ctx); >> >> // we need to send something that the EventSource on the client side >> // gets notified that the stream is open. >> push("welcome", "welcome"); >> } >> >> /// >> /// put a message into the fifo >> /// >> /// If \a send is false the messages are not dispatched >> /// immediately, you can dispatch them later by calling >> broadcast() or by calling push >> /// event with send=true >> /// >> void push(std::string const &data,bool send=true) >> { >> push(std::string(),data,send); >> } >> >> /// >> /// put a message into the fifo >> /// >> /// If \a send is false the messages are not dispatched >> /// immediately, you can dispatch them later by calling >> broadcast() or by calling push >> /// event with send=true >> /// >> void push(std::string const &event,std::string const &data,bool send=true) >> { >> message msg; >> msg.event = event; >> msg.data = data; >> >> mutex.lock(); >> messages_.push(msg); >> mutex.unlock(); >> >> if(send) >> broadcast(); >> } >> >> protected: >> bool on_sent(event_stream &es) >> { >> size_t last_id = es.last_integer_id(); >> size_t id = last_id; >> >> mutex.lock(); >> while (messages_.empty() == false) >> { >> id++; >> message &msg = messages_.front(); >> es.write(msg.data, id, msg.event); >> messages_.pop(); >> } >> mutex.unlock(); >> >> return true; >> } >> >> private: >> struct message { >> std::string event; >> std::string data; >> }; >> std::queue<message> messages_; >> booster::mutex mutex; >> }; >> >> } // namespace sse >> >> Oh... it is planed to have one SSE stream per session. >> If you need it I can provide you a simple demo application. >> > >Finally I got keep_alive working by changing on_send > > bool on_sent(event_stream &es) > { > bool something_send = false; > size_t last_id = es.last_integer_id(); > size_t id = last_id; > > mutex.lock(); > while (messages_.empty() == false) > { > id++; > message &msg = messages_.front(); > es.write(msg.data, id, msg.event); > messages_.pop(); > something_send = true; > } > mutex.unlock(); > > return something_send; > } > > >Now I am looking to prevent expiration of the user session. > >greets >-- >Christian Gmeiner, MSc > >------------------------------------------------------------------------------ >Own the Future-Intel(R) Level Up Game Demo Contest 2013 >Rise to greatness in Intel's independent game demo contest. Compete >for recognition, cash, and the chance to get your game on Steam. >$5K grand prize plus 10 genre and skill prizes. Submit your demo >by 6/6/13. http://altfarm.mediaplex.com/ad/ck/12124-176961-30367-2 >_______________________________________________ >Cppcms-users mailing list >Cpp...@li... >https://lists.sourceforge.net/lists/listinfo/cppcms-users > > > |
|
From: Artyom B. <art...@ya...> - 2013-04-02 11:34:57
|
Your code is incorrect, you must not use Mutexes...
Instead of this:
> void push(std::string const &event,std::string const &data,bool
> send=true)
> {
> message msg;
> msg.event = event;
> msg.data = data;
>
> mutex.lock();
> messages_.push(msg);
> mutex.unlock();
>
> if(send)
> broadcast();
> }
That I assume is called form an external thread you need to do something different
void thread_safe_push(std::string const &event,std::string const &data)
{ message msg;
msg.event = event;
msg.data = data;
service().post([=] { (lambda expression)
// EXECUTED IN THE EVENT LOOP THREAD!!!
messages_.push(msg);
broadcast();
});
}
or without C++11
void thread_safe_push(std::string const &event,std::string const &data)
{ message msg;
msg.event = event;
msg.data = data;
service().post(boost::bind(&event_fifo::thread_unsef_push,this,msg));
}
void thread_unsefe_push(message const &msg)
{ messages_.push(msg);
broadcast();
}
----- Original Message -----
> From: Christian Gmeiner <chr...@gm...>
> }
>
>
> My used SSE application looks like:
>
> SSE::SSE(cppcms::service &srv) : cppcms::application(srv)
> {
> stream_ = sse::event_fifo::create(srv.get_io_service());
> stream_->enable_keep_alive(1);
>
> dispatcher().assign("/get",&SSE::get,this);
> }
>
> void SSE::get()
> {
> stream_->accept(release_context());
> }
>
> void SSE::enqueue(std::string const &event, std::string const &data)
> {
> stream_->push(event, data);
> }
>
>
> And my used event_fifo class:
>
> class event_fifo : public event_source {
> protected:
> event_fifo(booster::aio::io_service &srv) :
> event_source(srv)
> {
> }
> public:
> ///
> /// Create a queue of maximal size \a size, such that user that
> connects too late
> /// it would be able to receive at most \a size latest messages
> ///
> static booster::shared_ptr<event_fifo> create(
> booster::aio::io_service &srv)
> {
> booster::shared_ptr<event_fifo> p(new event_fifo(srv));
> return p;
> }
>
> virtual void accept(booster::shared_ptr<cppcms::http::context> ctx)
> {
> // remove old messages
> mutex.lock();
> while (messages_.empty() == false)
> {
> messages_.pop();
> }
> mutex.unlock();
>
> event_source::accept(ctx);
>
> // we need to send something that the EventSource on the client side
> // gets notified that the stream is open.
> push("welcome", "welcome");
> }
>
> ///
> /// put a message into the fifo
> ///
> /// If \a send is false the messages are not dispatched
> /// immediately, you can dispatch them later by calling
> broadcast() or by calling push
> /// event with send=true
> ///
> void push(std::string const &data,bool send=true)
> {
> push(std::string(),data,send);
> }
>
> ///
> /// put a message into the fifo
> ///
> /// If \a send is false the messages are not dispatched
> /// immediately, you can dispatch them later by calling
> broadcast() or by calling push
> /// event with send=true
> ///
> void push(std::string const &event,std::string const &data,bool
> send=true)
> {
> message msg;
> msg.event = event;
> msg.data = data;
>
> mutex.lock();
> messages_.push(msg);
> mutex.unlock();
>
> if(send)
> broadcast();
> }
>
> protected:
> bool on_sent(event_stream &es)
> {
> size_t last_id = es.last_integer_id();
> size_t id = last_id;
>
> mutex.lock();
> while (messages_.empty() == false)
> {
> id++;
> message &msg = messages_.front();
> es.write(msg.data, id, msg.event);
> messages_.pop();
> }
> mutex.unlock();
>
> return true;
> }
>
> private:
> struct message {
> std::string event;
> std::string data;
> };
> std::queue<message> messages_;
> booster::mutex mutex;
> };
>
> } // namespace sse
>
> Oh... it is planed to have one SSE stream per session.
> If you need it I can provide you a simple demo application.
>
> greets
> --
> Christian Gmeiner, MSc
>
Artyom Beilis
--------------
CppCMS - C++ Web Framework: http://cppcms.com/
CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/
|
|
From: Christian G. <chr...@gm...> - 2013-04-02 16:15:56
|
2013/4/2 Artyom Beilis <art...@ya...>:
> Your code is incorrect, you must not use Mutexes...
>
> Instead of this:
>
>> void push(std::string const &event,std::string const &data,bool
>> send=true)
>> {
>> message msg;
>> msg.event = event;
>> msg.data = data;
>>
>> mutex.lock();
>> messages_.push(msg);
>> mutex.unlock();
>>
>> if(send)
>> broadcast();
>> }
>
>
> That I assume is called form an external thread you need to do something different
>
>
> void thread_safe_push(std::string const &event,std::string const &data)
> { message msg;
> msg.event = event;
> msg.data = data;
>
>
> service().post([=] { (lambda expression)
>
> // EXECUTED IN THE EVENT LOOP THREAD!!!
> messages_.push(msg);
> broadcast();
>
> });
>
> }
>
>
> or without C++11
>
> void thread_safe_push(std::string const &event,std::string const &data)
> { message msg;
> msg.event = event;
> msg.data = data;
>
>
> service().post(boost::bind(&event_fifo::thread_unsef_push,this,msg));
>
> }
>
>
> void thread_unsefe_push(message const &msg)
>
> { messages_.push(msg);
> broadcast();
>
> }
>
Thanks... I got rid of the mutex. Is there a way to renew a session? I
have tried to load() and save() the session during keep alive of the
event stream, but it does not work as expected.
void event_source::keep_alive(char const *comment)
{
if(closing_) {
return;
}
for(streamers_type::iterator
it=streamers_.begin();it!=streamers_.end();) {
booster::intrusive_ptr<details::post_send> ps = *it;
streamers_type::iterator tmp = it++;
streamers_.erase(tmp);
ps->stream().context()->response().out() << ':' <<
comment << "\n\n";
ps->stream().context()->async_flush_output(ps);
ps->stream().context()->session().load();
ps->stream().context()->session().save();
}
...
My current session timeout is set to 10 minutes. If a script gets
executed the GUI in the browser
shows a modal dialog with the output of the executed process - send via SSE.
If the script runs longer then session timeout and gc() gets called
the session will be removed. I want
to renew the session in the keep_alive action of the SSE stream.
greets
--
Christian Gmeiner, MSc
|
|
From: Christian G. <chr...@gm...> - 2013-04-02 16:59:02
|
2013/4/2 Christian Gmeiner <chr...@gm...>:
> 2013/4/2 Artyom Beilis <art...@ya...>:
>> Your code is incorrect, you must not use Mutexes...
>>
>> Instead of this:
>>
>>> void push(std::string const &event,std::string const &data,bool
>>> send=true)
>>> {
>>> message msg;
>>> msg.event = event;
>>> msg.data = data;
>>>
>>> mutex.lock();
>>> messages_.push(msg);
>>> mutex.unlock();
>>>
>>> if(send)
>>> broadcast();
>>> }
>>
>>
>> That I assume is called form an external thread you need to do something different
>>
>>
>> void thread_safe_push(std::string const &event,std::string const &data)
>> { message msg;
>> msg.event = event;
>> msg.data = data;
>>
>>
>> service().post([=] { (lambda expression)
>>
>> // EXECUTED IN THE EVENT LOOP THREAD!!!
>> messages_.push(msg);
>> broadcast();
>>
>> });
>>
>> }
>>
>>
>> or without C++11
>>
>> void thread_safe_push(std::string const &event,std::string const &data)
>> { message msg;
>> msg.event = event;
>> msg.data = data;
>>
>>
>> service().post(boost::bind(&event_fifo::thread_unsef_push,this,msg));
>>
>> }
>>
>>
>> void thread_unsefe_push(message const &msg)
>>
>> { messages_.push(msg);
>> broadcast();
>>
>> }
>>
>
> Thanks... I got rid of the mutex. Is there a way to renew a session? I
> have tried to load() and save() the session during keep alive of the
> event stream, but it does not work as expected.
>
> void event_source::keep_alive(char const *comment)
> {
> if(closing_) {
> return;
> }
> for(streamers_type::iterator
> it=streamers_.begin();it!=streamers_.end();) {
> booster::intrusive_ptr<details::post_send> ps = *it;
> streamers_type::iterator tmp = it++;
> streamers_.erase(tmp);
>
> ps->stream().context()->response().out() << ':' <<
> comment << "\n\n";
> ps->stream().context()->async_flush_output(ps);
>
> ps->stream().context()->session().load();
> ps->stream().context()->session().save();
> }
>
> ...
>
>
> My current session timeout is set to 10 minutes. If a script gets
> executed the GUI in the browser
> shows a modal dialog with the output of the executed process - send via SSE.
>
> If the script runs longer then session timeout and gc() gets called
> the session will be removed. I want
> to renew the session in the keep_alive action of the SSE stream.
>
As far as I can tell the session can only be loaded and saves once per
http_context. So
I added the following method:
void session_interface::renew_session()
{
loaded_ = 0;
saved_ = 0;
load();
save();
}
And now I can renew the session.
thanks
--
Christian Gmeiner, MSc
|
|
From: Artyom B. <art...@ya...> - 2013-04-02 20:15:01
|
Small notes: 1. Session is saved when the output stream is accessed first time, as you need to provide set session cookies. Remember the session data may be stored entirely on the client side in signed cookies. Saving session after output was provided is similar to an attempt to set a cookie **after** HTTP headers were sent. 2. Calling changing session values and calling save after the output was generated has undefined behavior. So your code is incorrect. I think you mix up two different things: HTTP Stream session - the state where the connection is open and you push the data to the stream (it is represented by cppcms::http::context and actual open TCP/IP socket) and the CppCMS/Web session the information shared **accorss** different connections - that is based cookies - the state for stateless HTTP. Artyom Beilis -------------- CppCMS - C++ Web Framework: http://cppcms.com/ CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/ ----- Original Message ----- > From: Christian Gmeiner <chr...@gm...> > To: Artyom Beilis <art...@ya...>; cpp...@li... > Cc: > Sent: Tuesday, April 2, 2013 7:58 PM > Subject: Re: [Cppcms-users] SSE keep-alive > > 2013/4/2 Christian Gmeiner <chr...@gm...>: >> 2013/4/2 Artyom Beilis <art...@ya...>: >>> Your code is incorrect, you must not use Mutexes... >>> >>> Instead of this: >>> >>>> void push(std::string const &event,std::string const > &data,bool >>>> send=true) >>>> { >>>> message msg; >>>> msg.event = event; >>>> msg.data = data; >>>> >>>> mutex.lock(); >>>> messages_.push(msg); >>>> mutex.unlock(); >>>> >>>> if(send) >>>> broadcast(); >>>> } >>> >>> >>> That I assume is called form an external thread you need to do > something different >>> >>> >>> void thread_safe_push(std::string const &event,std::string const > &data) >>> { message msg; >>> msg.event = event; >>> msg.data = data; >>> >>> >>> service().post([=] { (lambda expression) >>> >>> // EXECUTED IN THE EVENT LOOP THREAD!!! >>> messages_.push(msg); >>> broadcast(); >>> >>> }); >>> >>> } >>> >>> >>> or without C++11 >>> >>> void thread_safe_push(std::string const &event,std::string const > &data) >>> { message msg; >>> msg.event = event; >>> msg.data = data; >>> >>> >>> > service().post(boost::bind(&event_fifo::thread_unsef_push,this,msg)); >>> >>> } >>> >>> >>> void thread_unsefe_push(message const &msg) >>> >>> { messages_.push(msg); >>> broadcast(); >>> >>> } >>> >> >> Thanks... I got rid of the mutex. Is there a way to renew a session? I >> have tried to load() and save() the session during keep alive of the >> event stream, but it does not work as expected. >> >> void event_source::keep_alive(char const *comment) >> { >> if(closing_) { >> return; >> } >> for(streamers_type::iterator >> it=streamers_.begin();it!=streamers_.end();) { >> booster::intrusive_ptr<details::post_send> ps = *it; >> streamers_type::iterator tmp = it++; >> streamers_.erase(tmp); >> >> ps->stream().context()->response().out() << > ':' << >> comment << "\n\n"; >> ps->stream().context()->async_flush_output(ps); >> >> ps->stream().context()->session().load(); >> ps->stream().context()->session().save(); >> } >> >> ... >> >> >> My current session timeout is set to 10 minutes. If a script gets >> executed the GUI in the browser >> shows a modal dialog with the output of the executed process - send via > SSE. >> >> If the script runs longer then session timeout and gc() gets called >> the session will be removed. I want >> to renew the session in the keep_alive action of the SSE stream. >> > > As far as I can tell the session can only be loaded and saves once per > http_context. So > I added the following method: > > > void session_interface::renew_session() > { > loaded_ = 0; > saved_ = 0; > > load(); > save(); > } > > > And now I can renew the session. > > thanks > -- > Christian Gmeiner, MSc > |
|
From: Christian G. <chr...@gm...> - 2013-04-02 20:46:06
|
2013/4/2 Artyom Beilis <art...@ya...>:
> Small notes:
>
> 1. Session is saved when the output stream is accessed first time, as you
> need to provide set session cookies.
>
> Remember the session data may be stored entirely on the client
> side in signed cookies.
>
"session" : {
"expire" : "renew",
"timeout" : 15,
"location" : "server",
"gc" : 10,
"server": {
"storage":"memory"
}
},
The session data itself is store on the server side - or?
> Saving session after output was provided is similar to an attempt
> to set a cookie **after** HTTP headers were sent.
>
Okay
> 2. Calling changing session values and calling save after the output
> was generated has undefined behavior.
>
I am not changing any value stored in the session. I only want to renew
the session. For me it is a problem when the cppcms session gets deleted
if a script runs e.g. 15 minutes. On the client side there is only one open
SSE stream.
> So your code is incorrect.
>
> I think you mix up two different things: HTTP Stream session - the
> state where the connection is open and you push the data to the stream
> (it is represented by cppcms::http::context and actual open TCP/IP socket)
> and the CppCMS/Web session the information shared **accorss** different
> connections - that is based cookies - the state for stateless HTTP.
>
As far as I can tell from studying the source code a cppcms::http::context gets
created if the client does a get/post.
This context has access to the request(), the response() and the assigned cppcms
session().
In my case the life-time strategy is set to "renew". This means the
client needs to
do a get/post to create a cppcms::http::context as this action will
trigger the "renew"
logic - or?
Is there a way to do the "renew" of the cppcms::session from the server side?
Again from reading the code the cppcms::sessions::session_storage class
provides methods to load and save session data. The garbage logic is inside
such a inherited class.
If the session data is stored on the server side and the cookie in the
browser only stores
the session key it should be possible to renew a cppcms::session.
And this is what I doing in this code snippet.
void session_interface::renew_session()
{
loaded_ = 0;
saved_ = 0;
load();
save();
}
If there is no way to "renew" the cppcms::session on the server side, I need to
add some js code to the client side doing silly gets to trigger the "renew" of
the cppcms::session.
thanks
--
Christian Gmeiner, MSc
|
|
From: Artyom B. <art...@ya...> - 2013-04-03 06:48:05
|
----- Original Message -----
> 2013/4/2 Artyom Beilis <art...@ya...>:
>> Small notes:
>>
>> 1. Session is saved when the output stream is accessed first time, as you
>> need to provide set session cookies.
>>
>> Remember the session data may be stored entirely on the client
>> side in signed cookies.
>>
>
> "session" : {
> "expire" : "renew",
> "timeout" : 15,
> "location" : "server",
> "gc" : 10,
> "server": {
> "storage":"memory"
> }
> },
>
> The session data itself is store on the server side - or?
>
>> Saving session after output was provided is similar to an attempt
>> to set a cookie **after** HTTP headers were sent.
>>
>
> Okay
>
>> 2. Calling changing session values and calling save after the output
>> was generated has undefined behavior.
>>
>
> I am not changing any value stored in the session. I only want to renew
> the session. For me it is a problem when the cppcms session gets deleted
> if a script runs e.g. 15 minutes. On the client side there is only one open
> SSE stream.
Why wouldn't you increase the timeout on session such that it would not expire so quickly?
In general session is something long running - months, days, sometime hours for more sensitive
applications and tens of minutes for very sensitive applications like banking web sites.
The primary role of session is to carry user identification and other various user
specific properties.
>
>> So your code is incorrect.
>>
>> I think you mix up two different things: HTTP Stream session - the
>> state where the connection is open and you push the data to the stream
>> (it is represented by cppcms::http::context and actual open TCP/IP socket)
>> and the CppCMS/Web session the information shared **accorss** different
>> connections - that is based cookies - the state for stateless HTTP.
>>
>
> As far as I can tell from studying the source code a cppcms::http::context gets
> created if the client does a get/post.
> This context has access to the request(), the response() and the assigned cppcms
> session().
>
> In my case the life-time strategy is set to "renew". This means the
> client needs to
> do a get/post to create a cppcms::http::context as this action will
> trigger the "renew"
> logic - or?
>
> Is there a way to do the "renew" of the cppcms::session from the
> server side?
> Again from reading the code the cppcms::sessions::session_storage class
> provides methods to load and save session data. The garbage logic is inside
> such a inherited class.
No, if there is no request the session would get expired, regardless garbage
collection.
GC is needed to collect expired sessions but the session expiration does not
depend on GC, it is session specific property.
>
> If the session data is stored on the server side and the cookie in the
> browser only stores
> the session key it should be possible to renew a cppcms::session.
> And this is what I doing in this code snippet.
>
> void session_interface::renew_session()
> {
> loaded_ = 0;
> saved_ = 0;
>
> load();
> save();
> }
>
> If there is no way to "renew" the cppcms::session on the server side,
> I need to
> add some js code to the client side doing silly gets to trigger the
> "renew" of
> the cppcms::session.
>
I understand what you say but this is not something that is supported.
You may open a feature request to provide an access to server side
session storage from an API that is not connected to a specific
cppcms::http::context and renew session.
What you can actually do is to implement an alternative server side storage:
http://cppcms.com/cppcms_ref/1.0.2/classcppcms_1_1sessions_1_1session__storage.html
That would allow you to handle the timeout in different way and probably update
the session from your application directly.
But this is a hack.
> thanks
> --
> Christian Gmeiner, MSc
>
Artyom Beilis
--------------
CppCMS - C++ Web Framework: http://cppcms.com/
CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/
|
|
From: Christian G. <chr...@gm...> - 2013-04-03 08:04:43
|
2013/4/3 Artyom Beilis <art...@ya...>:
> ----- Original Message -----
>
>> 2013/4/2 Artyom Beilis <art...@ya...>:
>>> Small notes:
>>>
>>> 1. Session is saved when the output stream is accessed first time, as you
>>> need to provide set session cookies.
>>>
>>> Remember the session data may be stored entirely on the client
>>> side in signed cookies.
>>>
>>
>> "session" : {
>> "expire" : "renew",
>> "timeout" : 15,
>> "location" : "server",
>> "gc" : 10,
>> "server": {
>> "storage":"memory"
>> }
>> },
>>
>> The session data itself is store on the server side - or?
>>
>>> Saving session after output was provided is similar to an attempt
>>> to set a cookie **after** HTTP headers were sent.
>>>
>>
>> Okay
>>
>
>>> 2. Calling changing session values and calling save after the output
>>> was generated has undefined behavior.
>>>
>>
>> I am not changing any value stored in the session. I only want to renew
>> the session. For me it is a problem when the cppcms session gets deleted
>> if a script runs e.g. 15 minutes. On the client side there is only one open
>> SSE stream.
>
>
> Why wouldn't you increase the timeout on session such that it would not expire so quickly?
> In general session is something long running - months, days, sometime hours for more sensitive
> applications and tens of minutes for very sensitive applications like banking web sites.
>
There is a requirement that the user get logged out after 10 minutes
of inactivity as the application
is sensitive.
> The primary role of session is to carry user identification and other various user
> specific properties.
>
>>
>
>>> So your code is incorrect.
>>>
>>> I think you mix up two different things: HTTP Stream session - the
>>> state where the connection is open and you push the data to the stream
>>> (it is represented by cppcms::http::context and actual open TCP/IP socket)
>>> and the CppCMS/Web session the information shared **accorss** different
>>> connections - that is based cookies - the state for stateless HTTP.
>>>
>>
>> As far as I can tell from studying the source code a cppcms::http::context gets
>> created if the client does a get/post.
>> This context has access to the request(), the response() and the assigned cppcms
>> session().
>>
>> In my case the life-time strategy is set to "renew". This means the
>> client needs to
>> do a get/post to create a cppcms::http::context as this action will
>> trigger the "renew"
>> logic - or?
>>
>> Is there a way to do the "renew" of the cppcms::session from the
>> server side?
>> Again from reading the code the cppcms::sessions::session_storage class
>> provides methods to load and save session data. The garbage logic is inside
>> such a inherited class.
>
> No, if there is no request the session would get expired, regardless garbage
> collection.
>
That is not correct... if I am using my
session_interface::renew_session() method it
will trigger a call to
void session_storage::save(std::string const &key,time_t
to,std::string const &value)
which saves the session with a updated time_t to value. As a result of
this I am able
to renew a cppcms::session for hours - did run a test over the night.
So I think this works for server side stored sessions.
The only problem I see is that the cookie 'cppcms_session' - in my
case - expires as defined.
So I can not renew it on the browser side. That would mean that the
script runs nicely but if
any get/post gets triggered the cookie is not valid any more and the
user is not logged in.
>
> GC is needed to collect expired sessions but the session expiration does not
> depend on GC, it is session specific property.
>
It is yes... but if i call load() and save() the session expiration
gets updated.
>
>>
>> If the session data is stored on the server side and the cookie in the
>> browser only stores
>> the session key it should be possible to renew a cppcms::session.
>> And this is what I doing in this code snippet.
>>
>> void session_interface::renew_session()
>> {
>> loaded_ = 0;
>> saved_ = 0;
>>
>> load();
>> save();
>> }
>>
>> If there is no way to "renew" the cppcms::session on the server side,
>> I need to
>> add some js code to the client side doing silly gets to trigger the
>> "renew" of
>> the cppcms::session.
>>
>
> I understand what you say but this is not something that is supported.
>
> You may open a feature request to provide an access to server side
> session storage from an API that is not connected to a specific
> cppcms::http::context and renew session.
>
>
> What you can actually do is to implement an alternative server side storage:
>
> http://cppcms.com/cppcms_ref/1.0.2/classcppcms_1_1sessions_1_1session__storage.html
>
I am using my own session_storage as every session gets a own 'tmp'
folder to upload and
download data. This is also I need to 'renew' the session as a script
works on data stored in
such a 'tmp' folder. It would be bad to delete files inside the 'tmp'
folder if a script runs.
>
> That would allow you to handle the timeout in different way and probably update
> the session from your application directly.
>
> But this is a hack.
>
I am not interested in hacks which can not find its way back into the
upstream project like cppcms.
So the best would be to write some JS to handle my problem. Should not
be too hard to do
a 'keep_alive' get via ajax.
Thanks a lot for your time.
greets
--
Christian Gmeiner, MSc
--
Christian Gmeiner, MSc
2013/4/3 Artyom Beilis <art...@ya...>:
> ----- Original Message -----
>
>> 2013/4/2 Artyom Beilis <art...@ya...>:
>>> Small notes:
>>>
>>> 1. Session is saved when the output stream is accessed first time, as you
>>> need to provide set session cookies.
>>>
>>> Remember the session data may be stored entirely on the client
>>> side in signed cookies.
>>>
>>
>> "session" : {
>> "expire" : "renew",
>> "timeout" : 15,
>> "location" : "server",
>> "gc" : 10,
>> "server": {
>> "storage":"memory"
>> }
>> },
>>
>> The session data itself is store on the server side - or?
>>
>>> Saving session after output was provided is similar to an attempt
>>> to set a cookie **after** HTTP headers were sent.
>>>
>>
>> Okay
>>
>
>>> 2. Calling changing session values and calling save after the output
>>> was generated has undefined behavior.
>>>
>>
>> I am not changing any value stored in the session. I only want to renew
>> the session. For me it is a problem when the cppcms session gets deleted
>> if a script runs e.g. 15 minutes. On the client side there is only one open
>> SSE stream.
>
>
> Why wouldn't you increase the timeout on session such that it would not expire so quickly?
> In general session is something long running - months, days, sometime hours for more sensitive
> applications and tens of minutes for very sensitive applications like banking web sites.
>
> The primary role of session is to carry user identification and other various user
> specific properties.
>
>>
>
>>> So your code is incorrect.
>>>
>>> I think you mix up two different things: HTTP Stream session - the
>>> state where the connection is open and you push the data to the stream
>>> (it is represented by cppcms::http::context and actual open TCP/IP socket)
>>> and the CppCMS/Web session the information shared **accorss** different
>>> connections - that is based cookies - the state for stateless HTTP.
>>>
>>
>> As far as I can tell from studying the source code a cppcms::http::context gets
>> created if the client does a get/post.
>> This context has access to the request(), the response() and the assigned cppcms
>> session().
>>
>> In my case the life-time strategy is set to "renew". This means the
>> client needs to
>> do a get/post to create a cppcms::http::context as this action will
>> trigger the "renew"
>> logic - or?
>>
>> Is there a way to do the "renew" of the cppcms::session from the
>> server side?
>> Again from reading the code the cppcms::sessions::session_storage class
>> provides methods to load and save session data. The garbage logic is inside
>> such a inherited class.
>
> No, if there is no request the session would get expired, regardless garbage
> collection.
>
> GC is needed to collect expired sessions but the session expiration does not
> depend on GC, it is session specific property.
>
>
>>
>> If the session data is stored on the server side and the cookie in the
>> browser only stores
>> the session key it should be possible to renew a cppcms::session.
>> And this is what I doing in this code snippet.
>>
>> void session_interface::renew_session()
>> {
>> loaded_ = 0;
>> saved_ = 0;
>>
>> load();
>> save();
>> }
>>
>> If there is no way to "renew" the cppcms::session on the server side,
>> I need to
>> add some js code to the client side doing silly gets to trigger the
>> "renew" of
>> the cppcms::session.
>>
>
> I understand what you say but this is not something that is supported.
>
> You may open a feature request to provide an access to server side
> session storage from an API that is not connected to a specific
> cppcms::http::context and renew session.
>
>
> What you can actually do is to implement an alternative server side storage:
>
> http://cppcms.com/cppcms_ref/1.0.2/classcppcms_1_1sessions_1_1session__storage.html
>
>
> That would allow you to handle the timeout in different way and probably update
> the session from your application directly.
>
> But this is a hack.
>
>
>> thanks
>> --
>> Christian Gmeiner, MSc
>>
>
>
> Artyom Beilis
> --------------
> CppCMS - C++ Web Framework: http://cppcms.com/
> CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/
>
> ------------------------------------------------------------------------------
> Minimize network downtime and maximize team effectiveness.
> Reduce network management and security costs.Learn how to hire
> the most talented Cisco Certified professionals. Visit the
> Employer Resources Portal
> http://www.cisco.com/web/learning/employer_resources/index.html
> _______________________________________________
> Cppcms-users mailing list
> Cpp...@li...
> https://lists.sourceforge.net/lists/listinfo/cppcms-users
|
|
From: Markus R. <us...@ma...> - 2013-04-04 18:37:31
|
Hello! Artyom Beilis wrote: > I don't really understand why do you have mutex... > > You may not write to the event stream from a thread that is not the event > loop thread. > > If you want to notify the asynchronous SSE on anything you need to use > cppcms::service::post() with a callback that would be executed in the > event loop. It would be a good idea to say that clearly on the very top of http://cppcms.com/cppcms_ref/latest/classcppcms_1_1http_1_1context.html http://cppcms.com/cppcms_ref/latest/classcppcms_1_1http_1_1response.html (it would be the best if you use \warning or \note to make the pitfall more visible) It is otherwise not obvious that this limitation exists. best regards Markus |
|
From: Artyom B. <art...@ya...> - 2013-04-04 19:22:27
|
Actually I think I need to add a good tutorial about it. Artyom Beilis -------------- CppCMS - C++ Web Framework: http://cppcms.com/ CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/ >________________________________ > From: Markus Raab <us...@ma...> >To: cpp...@li... >Sent: Thursday, April 4, 2013 9:37 PM >Subject: Re: [Cppcms-users] SSE keep-alive > >Hello! > >Artyom Beilis wrote: >> I don't really understand why do you have mutex... >> >> You may not write to the event stream from a thread that is not the event >> loop thread. >> >> If you want to notify the asynchronous SSE on anything you need to use >> cppcms::service::post() with a callback that would be executed in the >> event loop. > >It would be a good idea to say that clearly on the very top of >http://cppcms.com/cppcms_ref/latest/classcppcms_1_1http_1_1context.html >http://cppcms.com/cppcms_ref/latest/classcppcms_1_1http_1_1response.html >(it would be the best if you use \warning or \note to make the pitfall more >visible) > >It is otherwise not obvious that this limitation exists. > >best regards >Markus > > >------------------------------------------------------------------------------ >Minimize network downtime and maximize team effectiveness. >Reduce network management and security costs.Learn how to hire >the most talented Cisco Certified professionals. Visit the >Employer Resources Portal >http://www.cisco.com/web/learning/employer_resources/index.html >_______________________________________________ >Cppcms-users mailing list >Cpp...@li... >https://lists.sourceforge.net/lists/listinfo/cppcms-users > > > |
|
From: Sergey <dan...@gm...> - 2013-04-06 19:11:24
|
Artyom Beilis <artyomtnk@...> writes: > > > Actually I think I need to add a good tutorial about it. Good idea. |