Browse Source

Client and library global context cleanup in case of incorrect shutdown handling (that is applications not correctly closing client after server has shutdown).

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@3207 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/1.9.1
sletz 16 years ago
parent
commit
171a3c4a0d
16 changed files with 108 additions and 61 deletions
  1. +4
    -0
      ChangeLog
  2. +5
    -5
      common/JackAPI.cpp
  3. +5
    -11
      common/JackClient.cpp
  4. +1
    -7
      common/JackClient.h
  5. +0
    -2
      common/JackClientControl.h
  6. +5
    -3
      common/JackError.cpp
  7. +12
    -5
      common/JackGlobals.cpp
  8. +17
    -4
      common/JackGlobals.h
  9. +3
    -1
      common/JackInternalClient.cpp
  10. +6
    -6
      common/JackLibAPI.cpp
  11. +3
    -2
      common/JackLibClient.cpp
  12. +22
    -1
      common/JackLibGlobals.h
  13. +6
    -6
      common/JackServerAPI.cpp
  14. +0
    -2
      common/ringbuffer.c
  15. +16
    -1
      tests/external_metro.cpp
  16. +3
    -5
      windows/portaudio/JackPortAudioDriver.cpp

+ 4
- 0
ChangeLog View File

@@ -23,6 +23,10 @@ Michael Voigt
Jackdmp changes log
---------------------------

2008-11-16 Stephane Letz <letz@grame.fr>

* Client and library global context cleanup in case of incorrect shutdown handling (that is applications not correctly closing client after server has shutdown).

2008-11-27 Stephane Letz <letz@grame.fr>

* Report ringbuffer.c fixes from jack1.


+ 5
- 5
common/JackAPI.cpp View File

@@ -259,7 +259,7 @@ static inline void WaitGraphChange()
graph change in RT context (just read the current graph state).
*/

if (jack_tls_get(gRealTime) == NULL) {
if (jack_tls_get(JackGlobals::fRealTime) == NULL) {
JackGraphManager* manager = GetGraphManager();
JackEngineControl* control = GetEngineControl();
assert(manager);
@@ -283,14 +283,14 @@ EXPORT void jack_set_info_function (print_function func)

EXPORT jack_client_t* jack_client_new(const char* client_name)
{
assert(gOpenMutex);
gOpenMutex->Lock();
assert(JackGlobals::fOpenMutex);
JackGlobals::fOpenMutex->Lock();
jack_error("jack_client_new: deprecated");
int options = JackUseExactName;
if (getenv("JACK_START_SERVER") == NULL)
options |= JackNoStartServer;
jack_client_t* res = jack_client_open_aux(client_name, (jack_options_t)options, NULL, NULL);
gOpenMutex->Unlock();
JackGlobals::fOpenMutex->Unlock();
return res;
}

@@ -628,7 +628,7 @@ EXPORT int jack_port_set_name(jack_port_t* port, const char* name)
JackGraphManager* manager = GetGraphManager();
int refnum;
if (manager && ((refnum = manager->GetPort(myport)->GetRefNum()) > 0)) {
JackClient* client = JackClient::fClientTable[refnum];
JackClient* client = JackGlobals::fClientTable[refnum];
assert(client);
return client->PortRename(myport, name);
} else {


+ 5
- 11
common/JackClient.cpp View File

@@ -37,8 +37,6 @@ using namespace std;
namespace Jack
{

JackClient* JackClient::fClientTable[CLIENT_NUM] = {};

#define IsRealTime() ((fProcess != NULL) | (fThreadFun != NULL) | (fSync != NULL) | (fTimebase != NULL))

JackClient::JackClient():fThread(this)
@@ -88,8 +86,8 @@ int JackClient::Close()
Deactivate();
fChannel->Stop(); // Channels is stopped first to avoid receiving notifications while closing
// Request close only is server is still running
if (GetClientControl()->fServer) {
// Request close only if server is still running
if (JackGlobals::fServerRunning) {
fChannel->ClientClose(GetClientControl()->fRefNum, &result);
} else {
jack_log("JackClient::Close server is shutdown");
@@ -97,7 +95,7 @@ int JackClient::Close()
fChannel->Close();
fSynchroTable[GetClientControl()->fRefNum].Disconnect();
fClientTable[GetClientControl()->fRefNum] = NULL;
JackGlobals::fClientTable[GetClientControl()->fRefNum] = NULL;
return result;
}

@@ -359,7 +357,7 @@ int JackClient::StartThread()
*/
bool JackClient::Execute()
{
if (!jack_tls_set(gRealTime, this))
if (!jack_tls_set(JackGlobals::fRealTime, this))
jack_error("failed to set thread realtime key");
if (GetEngineControl()->fRealTime)
@@ -596,11 +594,7 @@ ShutDown is called:
void JackClient::ShutDown()
{
jack_log("ShutDown");
// Be sure client is already started
if (GetClientControl()) {
GetClientControl()->fServer = false;
}
JackGlobals::fServerRunning = false;
if (fShutdown) {
fShutdown(fShutdownArg);


+ 1
- 7
common/JackClient.h View File

@@ -87,8 +87,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface
detail::JackClientChannelInterface* fChannel;
JackSynchro* fSynchroTable;
std::list<jack_port_id_t> fPortList;
bool fServerRunning;

int StartThread();
void SetupDriverSync(bool freewheel);
bool IsActive();
@@ -98,7 +97,6 @@ class JackClient : public JackClientInterface, public JackRunnableInterface
virtual int ClientNotifyImp(int refnum, const char* name, int notify, int sync, int value1, int value);

// Fons Adriaensen thread model
inline bool WaitFirstSync();
inline void ExecuteThread();
inline bool WaitSync();
@@ -140,7 +138,6 @@ class JackClient : public JackClientInterface, public JackRunnableInterface
virtual int PortDisconnect(jack_port_id_t src);

virtual int PortIsMine(jack_port_id_t port_index);
virtual int PortRename(jack_port_id_t port_index, const char* name);

// Transport
@@ -185,9 +182,6 @@ class JackClient : public JackClientInterface, public JackRunnableInterface
// JackRunnableInterface interface
bool Init();
bool Execute();
static JackClient* fClientTable[CLIENT_NUM];
};

// Each "side" server and client will implement this to get the shared graph manager, engine control and inter-process synchro table.


+ 0
- 2
common/JackClientControl.h View File

@@ -43,7 +43,6 @@ struct JackClientControl : public JackShmMemAble
int fRefNum;
int fPID;
bool fActive;
bool fServer;

JackClientControl(const char* name, int pid, int refnum)
{
@@ -78,7 +77,6 @@ struct JackClientControl : public JackShmMemAble
fTransportSync = false;
fTransportTimebase = false;
fActive = false;
fServer = true;
}

};


+ 5
- 3
common/JackError.cpp View File

@@ -27,9 +27,11 @@

int jack_verbose = 0;

using namespace Jack;

void change_thread_log_function(jack_log_function_t log_function)
{
if (!jack_tls_set(g_key_log_function, (void*)log_function))
if (!jack_tls_set(JackGlobals::fKeyLogFunction, (void*)log_function))
{
jack_error("failed to set thread log function");
}
@@ -37,7 +39,7 @@ void change_thread_log_function(jack_log_function_t log_function)

SERVER_EXPORT void set_threaded_log_function()
{
change_thread_log_function(Jack::JackMessageBufferAdd);
change_thread_log_function(JackMessageBufferAdd);
}

void jack_log_function(int level, const char *message)
@@ -74,7 +76,7 @@ static void jack_format_and_log(int level, const char *prefix, const char *fmt,

vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap);

log_function = (jack_log_function_t)jack_tls_get(g_key_log_function);
log_function = (jack_log_function_t)jack_tls_get(JackGlobals::fKeyLogFunction);

/* if log function is not overriden for thread, use default one */
if (log_function == NULL)


+ 12
- 5
common/JackGlobals.cpp View File

@@ -19,10 +19,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#include "JackGlobals.h"

jack_tls_key gRealTime;
static bool gKeyRealtimeInitialized = jack_tls_allocate_key(&gRealTime);
namespace Jack
{

jack_tls_key g_key_log_function;
static bool g_key_log_function_initialized = jack_tls_allocate_key(&g_key_log_function);
jack_tls_key JackGlobals::fRealTime;
static bool gKeyRealtimeInitialized = jack_tls_allocate_key(&JackGlobals::fRealTime);

JackMutex* gOpenMutex = new JackMutex();
jack_tls_key JackGlobals::fKeyLogFunction;
static bool fKeyLogFunctionInitialized = jack_tls_allocate_key(&JackGlobals::fKeyLogFunction);

JackMutex* JackGlobals::fOpenMutex = new JackMutex();
bool JackGlobals::fServerRunning = false;
JackClient* JackGlobals::fClientTable[CLIENT_NUM] = {};

} // end of namespace

+ 17
- 4
common/JackGlobals.h View File

@@ -21,11 +21,24 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define __JackGlobals__

#include "JackPlatformPlug.h"
#include "JackConstants.h"
#include "JackClient.h"

using namespace Jack;
namespace Jack
{

extern jack_tls_key gRealTime;
extern jack_tls_key g_key_log_function;
extern JackMutex* gOpenMutex;
// Globals used for client management on server or libray side.

struct JackGlobals {

static jack_tls_key fRealTime;
static jack_tls_key fKeyLogFunction;
static JackMutex* fOpenMutex;
static bool fServerRunning;
static JackClient* fClientTable[];
};

} // end of namespace

#endif

+ 3
- 1
common/JackInternalClient.cpp View File

@@ -141,7 +141,9 @@ int JackInternalClient::Open(const char* server_name, const char* name, jack_opt
}

SetupDriverSync(false);
fClientTable[fClientControl.fRefNum] = this;
JackGlobals::fClientTable[fClientControl.fRefNum] = this;
JackGlobals::fServerRunning = true;
jack_log("JackInternalClient::Open name = %s refnum = %ld", name_res, fClientControl.fRefNum);
return 0;

error:


+ 6
- 6
common/JackLibAPI.cpp View File

@@ -113,20 +113,20 @@ EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_opt

EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...)
{
assert(gOpenMutex);
gOpenMutex->Lock();
assert(JackGlobals::fOpenMutex);
JackGlobals::fOpenMutex->Lock();
va_list ap;
va_start(ap, status);
jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap);
va_end(ap);
gOpenMutex->Unlock();
JackGlobals::fOpenMutex->Unlock();
return res;
}

EXPORT int jack_client_close(jack_client_t* ext_client)
{
assert(gOpenMutex);
gOpenMutex->Lock();
assert(JackGlobals::fOpenMutex);
JackGlobals::fOpenMutex->Lock();
int res = -1;
jack_log("jack_client_close");
JackClient* client = (JackClient*)ext_client;
@@ -138,7 +138,7 @@ EXPORT int jack_client_close(jack_client_t* ext_client)
JackLibGlobals::Destroy(); // jack library destruction
jack_log("jack_client_close res = %d", res);
}
gOpenMutex->Unlock();
JackGlobals::fOpenMutex->Unlock();
return res;
}



+ 3
- 2
common/JackLibClient.cpp View File

@@ -70,7 +70,7 @@ JackLibClient::~JackLibClient()
int JackLibClient::Open(const char* server_name, const char* name, jack_options_t options, jack_status_t* status)
{
int shared_engine, shared_client, shared_graph, result;
jack_log("JackLibClient::Open %s", name);
jack_log("JackLibClient::Open name = %s", name);

snprintf(fServerName, sizeof(fServerName), server_name);

@@ -113,7 +113,8 @@ int JackLibClient::Open(const char* server_name, const char* name, jack_options_
goto error;
}
fClientTable[GetClientControl()->fRefNum] = this;
JackGlobals::fClientTable[GetClientControl()->fRefNum] = this;
JackGlobals::fServerRunning = true;
jack_log("JackLibClient::Open name = %s refnum = %ld", name_res, GetClientControl()->fRefNum);
return 0;



+ 22
- 1
common/JackLibGlobals.h View File

@@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "JackGraphManager.h"
#include "JackMessageBuffer.h"
#include "JackTime.h"
#include "JackClient.h"
#include "JackError.h"
#include <assert.h>
#include <signal.h>
@@ -44,7 +45,7 @@ struct JackLibGlobals
{
JackShmReadWritePtr<JackGraphManager> fGraphManager; /*! Shared memory Port manager */
JackShmReadWritePtr<JackEngineControl> fEngineControl; /*! Shared engine control */ // transport engine has to be writable
JackSynchro fSynchroTable[CLIENT_NUM]; /*! Shared synchro table */
JackSynchro fSynchroTable[CLIENT_NUM]; /*! Shared synchro table */
sigset_t fProcessSignals;
static int fClientCount;
@@ -86,6 +87,26 @@ struct JackLibGlobals

static void Init()
{
if (!JackGlobals::fServerRunning && fClientCount > 0) {
// Cleanup remaining clients
jack_error("Jack server was closed but clients are still allocated, cleanup...");
for (int i = 0; i < CLIENT_NUM; i++) {
JackClient* client = JackGlobals::fClientTable[i];
if (client) {
jack_error("Cleanup client ref = %d", i);
client->Close();
delete client;
JackGlobals::fClientTable[CLIENT_NUM] = NULL;
}
}
// Cleanup global context
fClientCount = 0;
delete fGlobals;
fGlobals = NULL;
}
if (fClientCount++ == 0 && !fGlobals) {
jack_log("JackLibGlobals Init %x", fGlobals);
InitTime();


+ 6
- 6
common/JackServerAPI.cpp View File

@@ -115,20 +115,20 @@ EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_opt

EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...)
{
assert(gOpenMutex);
gOpenMutex->Lock();
assert(JackGlobals::fOpenMutex);
JackGlobals::fOpenMutex->Lock();
va_list ap;
va_start(ap, status);
jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap);
va_end(ap);
gOpenMutex->Unlock();
JackGlobals::fOpenMutex->Unlock();
return res;
}

EXPORT int jack_client_close(jack_client_t* ext_client)
{
assert(gOpenMutex);
gOpenMutex->Lock();
assert(JackGlobals::fOpenMutex);
JackGlobals::fOpenMutex->Lock();
int res = -1;
jack_log("jack_client_close");
JackClient* client = (JackClient*)ext_client;
@@ -142,7 +142,7 @@ EXPORT int jack_client_close(jack_client_t* ext_client)
}
jack_log("jack_client_close res = %d", res);
}
gOpenMutex->Unlock();
JackGlobals::fOpenMutex->Unlock();
return res;
}



+ 0
- 2
common/ringbuffer.c View File

@@ -27,8 +27,6 @@
#endif /* USE_MLOCK */
#include "JackCompilerDeps.h"

// TODO : what to do with Paul fixes done av rev 3014 (http://trac.jackaudio.org/changeset/3014)

typedef struct {
char *buf;
size_t len;


+ 16
- 1
tests/external_metro.cpp View File

@@ -75,7 +75,7 @@ ExternalMetro::ExternalMetro(int freq, double max_amp, int dur_arg, int bpm, cha
}
if ((client = jack_client_open (client_name, options, &status)) == 0) {
fprintf (stderr, "jack server not running?\n");
return;
throw -1;
}

jack_set_process_callback (client, process_audio, this);
@@ -184,6 +184,21 @@ int main (int argc, char *argv[])

printf("Opening a new client....\n");
client1 = new ExternalMetro(1200, 0.4, 20, 80, "t1");
printf("Now quit the server, shutdown callback should be called...\n");
printf("Type 'c' to move on...\n");
while ((getchar() != 'c')) {
JackSleep(1);
};

printf("Simulating client not correctly closed...\n");
printf("Opening a new client....\n");
try {
client1 = new ExternalMetro(1200, 0.4, 20, 80, "t1");
} catch (int num) {
printf("Cannot open a new client since old one was not closed correctly... OK\n");
}

printf("Type 'q' to quit...\n");
while ((getchar() != 'q')) {


+ 3
- 5
windows/portaudio/JackPortAudioDriver.cpp View File

@@ -174,7 +174,7 @@ namespace Jack

error:
JackAudioDriver::Close();
jack_error ( "Can't open default PortAudio device : %s", Pa_GetErrorText(err) );
jack_error("Can't open default PortAudio device : %s", Pa_GetErrorText(err));
return -1;
}

@@ -436,8 +436,7 @@ extern "C"

case 'P':
playback = TRUE;
if (strcmp(param->value.str, "none") != 0)
{
if (strcmp(param->value.str, "none") != 0) {
playback_pcm_name = strdup(param->value.str);
}
break;
@@ -469,8 +468,7 @@ extern "C"
}

// duplex is the default
if (!capture && !playback)
{
if (!capture && !playback) {
capture = TRUE;
playback = TRUE;
}


Loading…
Cancel
Save