diff --git a/ChangeLog b/ChangeLog index 77a5edd3..0ccfb574 100644 --- a/ChangeLog +++ b/ChangeLog @@ -35,6 +35,10 @@ Chris Caudle Jackdmp changes log --------------------------- +2011-07-23 Stephane Letz + + * Possible fix for http://trac.jackaudio.org/ticket/193. + 2011-07-22 Stephane Letz * NetJack2: improve error reporting. diff --git a/common/JackChannel.h b/common/JackChannel.h index 69d25e00..5979ba8e 100644 --- a/common/JackChannel.h +++ b/common/JackChannel.h @@ -74,7 +74,7 @@ class JackClientChannelInterface return -1; } - virtual void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result) + virtual void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open) {} virtual void ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result) {} diff --git a/common/JackClient.cpp b/common/JackClient.cpp index 8c3c6de5..29890e58 100644 --- a/common/JackClient.cpp +++ b/common/JackClient.cpp @@ -149,6 +149,8 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, { int res = 0; + jack_log("JackClient::ClientNotify ref = %ld name = %s notify = %ld", refnum, name, notify); + // Done all time: redirected on subclass implementation JackLibClient and JackInternalClient switch (notify) { diff --git a/common/JackDriver.cpp b/common/JackDriver.cpp index e424ce28..54aef84a 100644 --- a/common/JackDriver.cpp +++ b/common/JackDriver.cpp @@ -217,6 +217,8 @@ void JackDriver::SetupDriverSync(int ref, bool freewheel) int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) { + jack_log("JackDriver::ClientNotify ref = %ld driver = %s name = %s notify = %ld", refnum, fClientControl.fName, name, notify); + switch (notify) { case kStartFreewheelCallback: @@ -228,7 +230,7 @@ int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, jack_log("JackDriver::kStopFreewheel"); SetupDriverSync(fClientControl.fRefNum, false); break; - } + } return 0; } diff --git a/common/JackEngine.cpp b/common/JackEngine.cpp index dfc3f9af..0acb2be9 100644 --- a/common/JackEngine.cpp +++ b/common/JackEngine.cpp @@ -275,10 +275,10 @@ int JackEngine::NotifyAddClient(JackClientInterface* new_client, const char* nam // Notify existing clients of the new client and new client of existing clients. for (int i = 0; i < CLIENT_NUM; i++) { JackClientInterface* old_client = fClientTable[i]; - if (old_client) { + if (old_client && old_client != new_client) { if (old_client->ClientNotify(refnum, name, kAddClient, true, "", 0, 0) < 0) { jack_error("NotifyAddClient old_client fails name = %s", old_client->GetClientControl()->fName); - return -1; + // Not considered as a failure... } if (new_client->ClientNotify(i, old_client->GetClientControl()->fName, kAddClient, true, "", 0, 0) < 0) { jack_error("NotifyAddClient new_client fails name = %s", name); @@ -296,7 +296,7 @@ void JackEngine::NotifyRemoveClient(const char* name, int refnum) for (int i = 0; i < CLIENT_NUM; i++) { JackClientInterface* client = fClientTable[i]; if (client) { - client->ClientNotify(refnum, name, kRemoveClient, true, "",0, 0); + client->ClientNotify(refnum, name, kRemoveClient, true, "", 0, 0); } } } @@ -563,7 +563,6 @@ int JackEngine::ClientExternalOpen(const char* name, int pid, int uuid, int* ref } else { strncpy(real_name, name, JACK_CLIENT_NAME_SIZE); } - EnsureUUID(uuid); } @@ -686,12 +685,12 @@ int JackEngine::ClientCloseAux(int refnum, JackClientInterface* client, bool wai int i; fGraphManager->GetInputPorts(refnum, ports); - for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY) ; i++) { + for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY); i++) { PortUnRegister(refnum, ports[i]); } fGraphManager->GetOutputPorts(refnum, ports); - for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY) ; i++) { + for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY); i++) { PortUnRegister(refnum, ports[i]); } diff --git a/common/JackExternalClient.cpp b/common/JackExternalClient.cpp index 54342f97..5fd1b60f 100644 --- a/common/JackExternalClient.cpp +++ b/common/JackExternalClient.cpp @@ -36,7 +36,7 @@ JackExternalClient::~JackExternalClient() int JackExternalClient::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) { int result = -1; - jack_log("JackExternalClient::ClientNotify ref = %ld name = %s notify = %ld", refnum, name, notify); + jack_log("JackExternalClient::ClientNotify ref = %ld client = %s name = %s notify = %ld", refnum, fClientControl->fName, name, notify); fChannel.ClientNotify(refnum, name, notify, sync, message, value1, value2, &result); return result; } @@ -49,17 +49,17 @@ int JackExternalClient::Open(const char* name, int pid, int refnum, int uuid, in jack_error("Cannot connect to client name = %s\n", name); return -1; } - + // Use "placement new" to allocate object in shared memory JackShmMemAble* shared_mem = static_cast(JackShmMem::operator new(sizeof(JackClientControl))); shared_mem->Init(); fClientControl = new(shared_mem) JackClientControl(name, pid, refnum, uuid); - + if (!fClientControl) { jack_error("Cannot allocate client shared memory segment"); return -1; } - + *shared_client = shared_mem->GetShmIndex(); jack_log("JackExternalClient::Open name = %s index = %ld base = %x", name, shared_mem->GetShmIndex(), shared_mem->GetShmAddress()); return 0; diff --git a/common/JackExternalClient.h b/common/JackExternalClient.h index c7c7fc42..19318a33 100644 --- a/common/JackExternalClient.h +++ b/common/JackExternalClient.h @@ -38,8 +38,8 @@ class JackExternalClient : public JackClientInterface private: - JackNotifyChannel fChannel; /*! Server/client communication channel */ - JackClientControl* fClientControl; /*! Client control in shared memory */ + JackNotifyChannel fChannel; /*! Server/client communication channel */ + JackClientControl* fClientControl; /*! Client control in shared memory */ public: diff --git a/common/JackInternalClient.cpp b/common/JackInternalClient.cpp index 9645f9d3..0882d5ad 100644 --- a/common/JackInternalClient.cpp +++ b/common/JackInternalClient.cpp @@ -71,13 +71,14 @@ int JackInternalClient::Open(const char* server_name, const char* name, int uuid strncpy(fServerName, server_name, sizeof(fServerName)); - fChannel->ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result); + fChannel->ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, false); if (result < 0) { int status1 = *status; - if (status1 & JackVersionError) + if (status1 & JackVersionError) { jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION); - else + } else { jack_error("Client name = %s conflits with another running client", name); + } goto error; } diff --git a/common/JackInternalClientChannel.h b/common/JackInternalClientChannel.h index dc81ac8c..eb986ae4 100644 --- a/common/JackInternalClientChannel.h +++ b/common/JackInternalClientChannel.h @@ -50,7 +50,7 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface return 0; } - void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result) + void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open) { *result = fEngine->ClientCheck(name, uuid, name_res, protocol, options, status); } diff --git a/common/JackLibClient.cpp b/common/JackLibClient.cpp index 2b54aa16..ffcd633b 100644 --- a/common/JackLibClient.cpp +++ b/common/JackLibClient.cpp @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -109,13 +109,13 @@ int JackLibClient::Open(const char* server_name, const char* name, int uuid, jac } SetupDriverSync(false); - + // Connect shared synchro : the synchro must be usable in I/O mode when several clients live in the same process if (!fSynchroTable[GetClientControl()->fRefNum].Connect(name_res, fServerName)) { jack_error("Cannot ConnectSemaphore %s client", name_res); goto error; } - + JackGlobals::fClientTable[GetClientControl()->fRefNum] = this; JackGlobals::fServerRunning = true; SetClockSource(GetEngineControl()->fClockSource); @@ -146,7 +146,7 @@ int JackLibClient::ClientNotifyImp(int refnum, const char* name, int notify, int case kRemoveClient: jack_log("JackClient::RemoveClient name = %s, ref = %ld ", name, refnum); - if (strcmp(GetClientControl()->fName, name) != 0) + if (GetClientControl() && strcmp(GetClientControl()->fName, name) != 0) res = fSynchroTable[refnum].Disconnect() ? 0 : -1; break; } diff --git a/common/JackNetTool.cpp b/common/JackNetTool.cpp index ee2c3c62..f5ee70a1 100644 --- a/common/JackNetTool.cpp +++ b/common/JackNetTool.cpp @@ -932,14 +932,12 @@ namespace Jack WORD wVersionRequested = MAKEWORD(2, 2); WSADATA wsaData; - if (WSAStartup(wVersionRequested, &wsaData) != 0) - { + if (WSAStartup(wVersionRequested, &wsaData) != 0) { jack_error("WSAStartup error : %s", strerror(NET_ERROR_CODE)); return -1; } - if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) - { + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { jack_error("Could not find a useable version of Winsock.dll\n"); WSACleanup(); return -1; diff --git a/common/JackRequest.h b/common/JackRequest.h index 90d0644a..43c1b7e0 100644 --- a/common/JackRequest.h +++ b/common/JackRequest.h @@ -138,11 +138,12 @@ struct JackClientCheckRequest : public JackRequest int fProtocol; int fOptions; int fUUID; + int fOpen; JackClientCheckRequest() {} - JackClientCheckRequest(const char* name, int protocol, int options, int uuid) - : JackRequest(JackRequest::kClientCheck), fProtocol(protocol), fOptions(options), fUUID(uuid) + JackClientCheckRequest(const char* name, int protocol, int options, int uuid, int open = false) + : JackRequest(JackRequest::kClientCheck), fProtocol(protocol), fOptions(options), fUUID(uuid), fOpen(open) { snprintf(fName, sizeof(fName), "%s", name); } @@ -152,7 +153,8 @@ struct JackClientCheckRequest : public JackRequest CheckRes(trans->Read(&fName, sizeof(fName))); CheckRes(trans->Read(&fProtocol, sizeof(int))); CheckRes(trans->Read(&fOptions, sizeof(int))); - return trans->Read(&fUUID, sizeof(int)); + CheckRes(trans->Read(&fUUID, sizeof(int))); + return trans->Read(&fOpen, sizeof(int)); } int Write(JackChannelTransaction* trans) @@ -161,7 +163,8 @@ struct JackClientCheckRequest : public JackRequest CheckRes(trans->Write(&fName, sizeof(fName))); CheckRes(trans->Write(&fProtocol, sizeof(int))); CheckRes(trans->Write(&fOptions, sizeof(int))); - return trans->Write(&fUUID, sizeof(int)); + CheckRes(trans->Write(&fUUID, sizeof(int))); + return trans->Write(&fOpen, sizeof(int)); } }; diff --git a/posix/JackPosixSemaphore.cpp b/posix/JackPosixSemaphore.cpp index 0be9fdb5..91e9d601 100644 --- a/posix/JackPosixSemaphore.cpp +++ b/posix/JackPosixSemaphore.cpp @@ -187,7 +187,7 @@ bool JackPosixSemaphore::ConnectOutput(const char* name, const char* server_name bool JackPosixSemaphore::Disconnect() { if (fSemaphore) { - jack_log("JackPosixSemaphore::Disconnect name = %s", fName); + jack_log("JackPosixSemaphore::Disconnect name = %s", fName); if (sem_close(fSemaphore) != 0) { jack_error("Disconnect: can't disconnect named semaphore name = %s err = %s", fName, strerror(errno)); return false; diff --git a/posix/JackSocket.cpp b/posix/JackSocket.cpp index 6d7d6879..2157a455 100644 --- a/posix/JackSocket.cpp +++ b/posix/JackSocket.cpp @@ -188,6 +188,7 @@ int JackClientSocket::Read(void* data, int len) jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno)); return 0; } else { + jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno)); return -1; } } else { @@ -232,6 +233,7 @@ int JackClientSocket::Write(void* data, int len) jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno)); return 0; } else { + jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno)); return -1; } } else { diff --git a/posix/JackSocketClientChannel.cpp b/posix/JackSocketClientChannel.cpp index 23555c1d..1cc21550 100644 --- a/posix/JackSocketClientChannel.cpp +++ b/posix/JackSocketClientChannel.cpp @@ -62,13 +62,14 @@ int JackSocketClientChannel::Open(const char* server_name, const char* name, int } // Check name in server - ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result); + ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, true); if (result < 0) { int status1 = *status; - if (status1 & JackVersionError) + if (status1 & JackVersionError) { jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION); - else + } else { jack_error("Client name = %s conflits with another running client", name); + } goto error; } @@ -141,9 +142,9 @@ void JackSocketClientChannel::ServerAsyncCall(JackRequest* req, JackResult* res, } } -void JackSocketClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result) +void JackSocketClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open) { - JackClientCheckRequest req(name, protocol, options, uuid); + JackClientCheckRequest req(name, protocol, options, uuid, open); JackClientCheckResult res; ServerSyncCall(&req, &res, result); *status = res.fStatus; diff --git a/posix/JackSocketClientChannel.h b/posix/JackSocketClientChannel.h index 8e2b0e30..50da7de7 100644 --- a/posix/JackSocketClientChannel.h +++ b/posix/JackSocketClientChannel.h @@ -60,7 +60,7 @@ class JackSocketClientChannel : public detail::JackClientChannelInterface, publi int ServerCheck(const char* server_name); - void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result); + void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open); void ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result); void ClientOpen(const char* name, int* ref, int uuid, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, int* result) {} diff --git a/posix/JackSocketServerChannel.cpp b/posix/JackSocketServerChannel.cpp index 2c5f267e..5b7a5324 100644 --- a/posix/JackSocketServerChannel.cpp +++ b/posix/JackSocketServerChannel.cpp @@ -164,7 +164,7 @@ bool JackSocketServerChannel::HandleRequest(int fd) JackRequest header; if (header.Read(socket) < 0) { jack_log("HandleRequest: cannot read header"); - ClientKill(fd); // TO CHECK SOLARIS + ClientKill(fd); return false; } @@ -185,6 +185,9 @@ bool JackSocketServerChannel::HandleRequest(int fd) res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus); if (res.Write(socket) < 0) jack_error("JackRequest::ClientCheck write error name = %s", req.fName); + // Atomic ClientCheck followed by ClientOpen on same socket + if (req.fOpen) + HandleRequest(fd); break; } diff --git a/windows/JackWinNamedPipeClientChannel.cpp b/windows/JackWinNamedPipeClientChannel.cpp index f29f7ff5..e4b6ecb4 100644 --- a/windows/JackWinNamedPipeClientChannel.cpp +++ b/windows/JackWinNamedPipeClientChannel.cpp @@ -55,10 +55,10 @@ int JackWinNamedPipeClientChannel::Open(const char* server_name, const char* nam /* 16/08/07: was called before doing "fRequestPipe.Connect" .... still necessary? - if (fNotificationListenPipe.Bind(jack_client_dir, name, 0) < 0) { - jack_error("Cannot bind pipe"); - goto error; - } + if (fNotificationListenPipe.Bind(jack_client_dir, name, 0) < 0) { + jack_error("Cannot bind pipe"); + goto error; + } */ if (fRequestPipe.Connect(jack_server_dir, server_name, 0) < 0) { @@ -67,10 +67,14 @@ int JackWinNamedPipeClientChannel::Open(const char* server_name, const char* nam } // Check name in server - ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result); + ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, true); if (result < 0) { - jack_error("Client name = %s conflits with another running client", name); - goto error; + int status1 = *status; + if (status1 & JackVersionError) { + jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION); + } else { + jack_error("Client name = %s conflits with another running client", name); + } } if (fNotificationListenPipe.Bind(jack_client_dir, name_res, 0) < 0) { @@ -142,9 +146,9 @@ void JackWinNamedPipeClientChannel::ServerAsyncCall(JackRequest* req, JackResult } } -void JackWinNamedPipeClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result) +void JackWinNamedPipeClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open) { - JackClientCheckRequest req(name, protocol, options, uuid); + JackClientCheckRequest req(name, protocol, options, uuid, open); JackClientCheckResult res; ServerSyncCall(&req, &res, result); *status = res.fStatus; diff --git a/windows/JackWinNamedPipeClientChannel.h b/windows/JackWinNamedPipeClientChannel.h index 479e3271..7b84eba8 100644 --- a/windows/JackWinNamedPipeClientChannel.h +++ b/windows/JackWinNamedPipeClientChannel.h @@ -59,7 +59,7 @@ class JackWinNamedPipeClientChannel : public detail::JackClientChannelInterface, int ServerCheck(const char* server_name); - void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result); + void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open); void ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result); void ClientOpen(const char* name, int* ref, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, int* result) {} diff --git a/windows/JackWinNamedPipeServerChannel.cpp b/windows/JackWinNamedPipeServerChannel.cpp index de2fd397..75fa7d27 100644 --- a/windows/JackWinNamedPipeServerChannel.cpp +++ b/windows/JackWinNamedPipeServerChannel.cpp @@ -117,6 +117,9 @@ bool JackClientPipeThread::HandleRequest() if (req.Read(fPipe) == 0) res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus); res.Write(fPipe); + // Atomic ClientCheck followed by ClientOpen on same pipe + if (req.fOpen) + HandleRequest(); break; } @@ -478,11 +481,11 @@ int JackWinNamedPipeServerChannel::Open(const char* server_name, JackServer* ser void JackWinNamedPipeServerChannel::Close() { /* TODO : solve WIN32 thread Kill issue - This would hang the server... since we are quitting it, its not really problematic, - all ressources will be deallocated at the end. + This would hang the server... since we are quitting it, its not really problematic, + all ressources will be deallocated at the end. - fRequestListenPipe.Close(); - fThread.Stop(); + fRequestListenPipe.Close(); + fThread.Stop(); */ fThread.Kill();