Commit a4604f7c authored by sletz's avatar sletz
Browse files

Use a QUIT notification to properly quit the server channel, the server...

Use a QUIT notification to properly quit the server channel, the server channel thread can then be 'stopped' instead of 'canceled'

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@3853 0c269be4-1314-0410-8aa9-9f06e86f4224
parent 0f041ccc
......@@ -27,6 +27,11 @@ Josh Green
Jackdmp changes log
---------------------------
2009-12-10 Stephane Letz <letz@grame.fr>
* Use a QUIT notification to properly quit the server channel, the server channel thread can then be 'stopped' instead of 'canceled'.
2009-12-09 Stephane Letz <letz@grame.fr>
* When threads are cancelled, the exception has to be rethrown.
......
......@@ -89,6 +89,11 @@ int JackEngine::Close()
return 0;
}
void JackEngine::NotifyQuit()
{
fChannel.NotifyQuit();
}
//-----------------------------
// Client ressource management
......
......@@ -79,7 +79,7 @@ class SERVER_EXPORT JackEngine
int Open();
int Close();
// Client management
int ClientCheck(const char* name, char* name_res, int protocol, int options, int* status);
int ClientExternalOpen(const char* name, int pid, int* ref, int* shared_engine, int* shared_client, int* shared_graph_manager);
......@@ -122,6 +122,7 @@ class SERVER_EXPORT JackEngine
void NotifyBufferSize(jack_nframes_t buffer_size);
void NotifySampleRate(jack_nframes_t sample_rate);
void NotifyFreewheel(bool onoff);
void NotifyQuit();
};
......
......@@ -75,6 +75,24 @@ class SERVER_EXPORT JackTemporaryException : public JackException {
{}
};
/*!
\brief
*/
class SERVER_EXPORT JackQuitException : public JackException {
public:
JackQuitException(const std::string& msg) : JackException(msg)
{}
JackQuitException(char* msg) : JackException(msg)
{}
JackQuitException(const char* msg) : JackException(msg)
{}
JackQuitException() : JackException("")
{}
};
/*!
\brief Exception possibly thrown by Net slaves.
*/
......
......@@ -54,7 +54,7 @@ catch (...) {
throw; \
} \
#define CATCH_ENGINE_EXCEPTION \
#define CATCH_EXCEPTION \
} catch(std::bad_alloc& e) { \
jack_error("Memory allocation error..."); \
} catch (...) { \
......@@ -94,7 +94,7 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
return fEngine.Close();
CATCH_EXCEPTION_RETURN
}
// Client management
int ClientCheck(const char* name, char* name_res, int protocol, int options, int* status)
{
......@@ -244,35 +244,35 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
TRY_CALL
JackLock lock(this);
fEngine.NotifyXRun(refnum);
CATCH_ENGINE_EXCEPTION
CATCH_EXCEPTION
}
void NotifyGraphReorder()
{
TRY_CALL
JackLock lock(this);
fEngine.NotifyGraphReorder();
CATCH_ENGINE_EXCEPTION
CATCH_EXCEPTION
}
void NotifyBufferSize(jack_nframes_t buffer_size)
{
TRY_CALL
JackLock lock(this);
fEngine.NotifyBufferSize(buffer_size);
CATCH_ENGINE_EXCEPTION
CATCH_EXCEPTION
}
void NotifySampleRate(jack_nframes_t sample_rate)
{
TRY_CALL
JackLock lock(this);
fEngine.NotifySampleRate(sample_rate);
CATCH_ENGINE_EXCEPTION
CATCH_EXCEPTION
}
void NotifyFreewheel(bool onoff)
{
TRY_CALL
JackLock lock(this);
fEngine.NotifyFreewheel(onoff);
CATCH_ENGINE_EXCEPTION
CATCH_EXCEPTION
}
void NotifyFailure(int code, const char* reason)
......@@ -280,7 +280,7 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
TRY_CALL
JackLock lock(this);
fEngine.NotifyFailure(code, reason);
CATCH_ENGINE_EXCEPTION
CATCH_EXCEPTION
}
int GetClientPID(const char* name)
......@@ -298,7 +298,15 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
return fEngine.GetClientRefNum(name);
CATCH_EXCEPTION_RETURN
}
void NotifyQuit()
{
TRY_CALL
JackLock lock(this);
return fEngine.NotifyQuit();
CATCH_EXCEPTION
}
};
} // end of namespace
......
......@@ -44,6 +44,7 @@ enum NotificationType {
kPortRenameCallback = 13,
kRealTimeCallback = 14,
kShutDownCallback = 15,
kQUIT = 16,
kMaxNotification
};
......
......@@ -125,6 +125,7 @@ fail_close1:
int JackServer::Close()
{
jack_log("JackServer::Close");
fEngine->NotifyQuit();
fChannel.Close();
fAudioDriver->Detach();
fAudioDriver->Close();
......
......@@ -412,7 +412,7 @@ int main(int argc, char* argv[])
// Audio driver
audio_driver_ctl = jackctl_server_get_driver(server_ctl, audio_driver_name);
if (audio_driver_ctl == NULL) {
fprintf(stderr, "Unkown driver \"%s\"\n", audio_driver_name);
fprintf(stderr, "Unknown driver \"%s\"\n", audio_driver_name);
goto fail_free1;
}
......@@ -450,7 +450,7 @@ int main(int argc, char* argv[])
midi_driver_ctl = jackctl_server_get_driver(server_ctl, midi_driver_name);
if (midi_driver_ctl == NULL) {
fprintf(stderr, "Unkown driver \"%s\"\n", midi_driver_name);
fprintf(stderr, "Unknown driver \"%s\"\n", midi_driver_name);
goto fail_free2;
}
......
......@@ -18,9 +18,11 @@ This program is free software; you can redistribute it and/or modify
*/
#include "JackServer.h"
#include "JackNotification.h"
#include "JackLockedEngine.h"
#include "JackRPCEngine.h"
#include "JackMachServerChannel.h"
#include "JackException.h"
#include <assert.h>
using namespace Jack;
......@@ -238,6 +240,11 @@ rpc_type server_rpc_jack_client_rt_notify(mach_port_t server_port, int refnum, i
JackMachServerChannel* channel = JackMachServerChannel::fPortTable[server_port];
assert(channel);
assert(channel->GetServer());
channel->GetServer()->Notify(refnum, notify, value);
return KERN_SUCCESS;
if (notify == kQUIT) {
throw JackQuitException();
} else {
channel->GetServer()->Notify(refnum, notify, value);
return KERN_SUCCESS;
}
}
......@@ -58,7 +58,7 @@ int JackMachServerChannel::Open(const char* server_name, JackServer* server)
void JackMachServerChannel::Close()
{
jack_log("JackMachServerChannel::Close");
fThread.Kill();
fThread.Stop();
fServerPort.DestroyPort();
}
......@@ -149,12 +149,19 @@ boolean_t JackMachServerChannel::MessageHandler(mach_msg_header_t* Request, mach
bool JackMachServerChannel::Execute()
{
kern_return_t res;
if ((res = mach_msg_server(MessageHandler, 1024, fServerPort.GetPortSet(), 0)) != KERN_SUCCESS) {
jack_log("JackMachServerChannel::Execute: err = %s", mach_error_string(res));
try {
kern_return_t res;
if ((res = mach_msg_server(MessageHandler, 1024, fServerPort.GetPortSet(), 0)) != KERN_SUCCESS) {
jack_log("JackMachServerChannel::Execute: err = %s", mach_error_string(res));
return false;
}
return true;
} catch (JackQuitException& e) {
jack_log("JackMachServerChannel::Execute JackQuitException");
return false;
}
//return (res == KERN_SUCCESS); mach_msg_server can fail if the client reply port is not valid anymore (crashed client)
return true;
}
} // end of namespace
......
......@@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "JackMachServerNotifyChannel.h"
#include "JackRPCEngineUser.c"
#include "JackNotification.h"
#include "JackTools.h"
#include "JackConstants.h"
#include "JackError.h"
......@@ -42,9 +43,7 @@ int JackMachServerNotifyChannel::Open(const char* server_name)
}
void JackMachServerNotifyChannel::Close()
{
//fClientPort.DisconnectPort(); pas ncessaire car le JackMachServerChannel a dja disparu?
}
{}
void JackMachServerNotifyChannel::Notify(int refnum, int notify, int value)
{
......@@ -53,6 +52,14 @@ void JackMachServerNotifyChannel::Notify(int refnum, int notify, int value)
jack_error("Could not write request ref = %d notify = %d err = %s", refnum, notify, mach_error_string(res));
}
}
void JackMachServerNotifyChannel::NotifyQuit()
{
kern_return_t res = rpc_jack_client_rt_notify(fClientPort.GetPort(), -1, kQUIT, 0, 0);
if (res != KERN_SUCCESS) {
jack_error("Could not write request ref = %d notify = %d err = %s", -1, kQUIT, mach_error_string(res));
}
}
} // end of namespace
......
......@@ -46,7 +46,8 @@ class JackMachServerNotifyChannel
void Close(); // Close the Server/Client connection
void Notify(int refnum, int notify, int value);
};
void NotifyQuit();
};
} // end of namespace
......
......@@ -26,6 +26,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "JackClient.h"
#include "JackTools.h"
#include "JackNotification.h"
#include "JackException.h"
#include <assert.h>
#include <signal.h>
......@@ -64,7 +66,7 @@ int JackSocketServerChannel::Open(const char* server_name, JackServer* server)
void JackSocketServerChannel::Close()
{
fThread.Kill();
fThread.Stop();
fRequestListenSocket.Close();
// Close remaining client sockets
......@@ -387,8 +389,14 @@ bool JackSocketServerChannel::HandleRequest(int fd)
case JackRequest::kNotification: {
jack_log("JackRequest::Notification");
JackClientNotificationRequest req;
if (req.Read(socket) == 0)
fServer->Notify(req.fRefNum, req.fNotify, req.fValue);
if (req.Read(socket) == 0) {
if (req.fNotify == kQUIT) {
jack_log("JackRequest::Notification kQUIT");
throw JackQuitException();
} else {
fServer->Notify(req.fRefNum, req.fNotify, req.fValue);
}
}
break;
}
......@@ -436,35 +444,42 @@ bool JackSocketServerChannel::Init()
bool JackSocketServerChannel::Execute()
{
// Global poll
if ((poll(fPollTable, fSocketTable.size() + 1, 10000) < 0) && (errno != EINTR)) {
jack_error("Engine poll failed err = %s request thread quits...", strerror(errno));
return false;
} else {
// Poll all clients
for (unsigned int i = 1; i < fSocketTable.size() + 1; i++) {
int fd = fPollTable[i].fd;
jack_log("fPollTable i = %ld fd = %ld", i, fd);
if (fPollTable[i].revents & ~POLLIN) {
jack_log("Poll client error err = %s", strerror(errno));
ClientKill(fd);
} else if (fPollTable[i].revents & POLLIN) {
if (!HandleRequest(fd))
jack_log("Could not handle external client request");
try {
// Global poll
if ((poll(fPollTable, fSocketTable.size() + 1, 10000) < 0) && (errno != EINTR)) {
jack_error("Engine poll failed err = %s request thread quits...", strerror(errno));
return false;
} else {
// Poll all clients
for (unsigned int i = 1; i < fSocketTable.size() + 1; i++) {
int fd = fPollTable[i].fd;
jack_log("fPollTable i = %ld fd = %ld", i, fd);
if (fPollTable[i].revents & ~POLLIN) {
jack_log("Poll client error err = %s", strerror(errno));
ClientKill(fd);
} else if (fPollTable[i].revents & POLLIN) {
if (!HandleRequest(fd))
jack_log("Could not handle external client request");
}
}
// Check the server request socket */
if (fPollTable[0].revents & POLLERR)
jack_error("Error on server request socket err = %s", strerror(errno));
if (fPollTable[0].revents & POLLIN)
ClientCreate();
}
// Check the server request socket */
if (fPollTable[0].revents & POLLERR)
jack_error("Error on server request socket err = %s", strerror(errno));
if (fPollTable[0].revents & POLLIN)
ClientCreate();
BuildPoolTable();
return true;
} catch (JackQuitException& e) {
jack_log("JackMachServerChannel::Execute JackQuitException");
return false;
}
BuildPoolTable();
return true;
}
} // end of namespace
......
......@@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "JackError.h"
#include "JackRequest.h"
#include "JackConstants.h"
#include "JackNotification.h"
namespace Jack
{
......@@ -55,6 +56,15 @@ void JackSocketServerNotifyChannel::Notify(int refnum, int notify, int value)
}
}
void JackSocketServerNotifyChannel::NotifyQuit()
{
JackClientNotificationRequest req(-1, kQUIT, 0);
if (req.Write(&fRequestSocket) < 0) {
jack_error("Could not write request ref = %d notify = %d", -1, kQUIT);
}
}
} // end of namespace
......@@ -44,6 +44,7 @@ class JackSocketServerNotifyChannel
void Close();
void Notify(int refnum, int notify, int value);
void NotifyQuit();
};
} // end of namespace
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment