From f62f984b97613807c8c75ef9358b00b96cec48ff Mon Sep 17 00:00:00 2001 From: Stephane Letz Date: Sat, 23 Jul 2011 12:11:29 +0200 Subject: [PATCH] Possible fix for http://trac.jackaudio.org/ticket/193. --- common/JackChannel.h | 2 +- common/JackEngine.cpp | 5 ++--- common/JackExternalClient.h | 4 ++-- common/JackInternalClient.cpp | 5 +++-- common/JackLibClient.cpp | 8 ++++---- common/JackNetTool.cpp | 6 ++---- common/JackRequest.h | 11 +++++++---- posix/JackSocketClientChannel.cpp | 11 ++++++----- posix/JackSocketClientChannel.h | 2 +- posix/JackSocketServerChannel.cpp | 5 ++++- windows/JackWinNamedPipeClientChannel.cpp | 22 +++++++++++++--------- windows/JackWinNamedPipeClientChannel.h | 2 +- windows/JackWinNamedPipeServerChannel.cpp | 11 +++++++---- 13 files changed, 53 insertions(+), 41 deletions(-) diff --git a/common/JackChannel.h b/common/JackChannel.h index 69d25e00..bb79d456 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 = false) {} 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/JackEngine.cpp b/common/JackEngine.cpp index dfc3f9af..a8fdffe9 100644 --- a/common/JackEngine.cpp +++ b/common/JackEngine.cpp @@ -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.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..fc2e9a7f 100644 --- a/common/JackInternalClient.cpp +++ b/common/JackInternalClient.cpp @@ -74,10 +74,11 @@ int JackInternalClient::Open(const char* server_name, const char* name, int uuid fChannel->ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result); 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/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 791af963..0b57cf6e 100644 --- a/common/JackNetTool.cpp +++ b/common/JackNetTool.cpp @@ -943,14 +943,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/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();