Skip to content

Commit

Permalink
Fixed sporadic xrun bug in shared memory code.
Browse files Browse the repository at this point in the history
This one was hard to track down. The symptom was that a few times,
sometimes several hours apart, the native plugin code would take much
longer than normal to complete, causing xruns for the plugin host.

It turns out that since the shared memory being used is backed by a
file, the Linux kernel likes to flush the contents in memory back to
the file occasionally. While it does this *it locks the memory
pages*, meaning that the plugin, which tries to write to the memory,
is suspended until the file write is complete.

Of course, waiting for file I/O inside the realtime code is
unacceptable, so we need shared memory that does not flush to disk.
The fix was to switch to POSIX shared memory objects, using
shm_open(), instead of normal file open().

Also fixed a trivial bug where the shared memory was opened twice
(mkstemp already opens the file, but we still opened it again
afterwards).
  • Loading branch information
falkTX committed Aug 27, 2012
1 parent 2cefab1 commit 059098b
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 22 deletions.
36 changes: 36 additions & 0 deletions paths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

#include <iostream>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

std::vector<std::string>
Paths::getPath(std::string envVar, std::string deflt, std::string defltHomeRelPath)
Expand Down Expand Up @@ -39,3 +44,34 @@ Paths::getPath(std::string envVar, std::string deflt, std::string defltHomeRelPa

return pathList;
}

// Behaves like mkstemp, but for shared memory.
int shm_mkstemp(char *fileBase)
{
const char charSet[] = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
int size = strlen(fileBase);
if (size < 6) {
errno = EINVAL;
return -1;
}

if (strcmp(fileBase + size - 6, "XXXXXX") != 0) {
errno = EINVAL;
return -1;
}

while (1) {
for (int c = size - 6; c < size; c++) {
// Note the -1 to avoid the trailing '\0' in charSet.
fileBase[c] = charSet[rand() % (sizeof(charSet) - 1)];
}
int fd = shm_open(fileBase, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fd >= 0) {
return fd;
} else if (errno != EEXIST) {
return -1;
}
}
}
2 changes: 2 additions & 0 deletions paths.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ class Paths
std::string defltHomeRelPath);
};

int shm_mkstemp(char *fileBase);

#endif
29 changes: 11 additions & 18 deletions remotepluginclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

#include "remotepluginclient.h"
#include "paths.h"

#include <sys/mman.h>
#include <sys/types.h>
Expand Down Expand Up @@ -40,6 +41,8 @@ RemotePluginClient::RemotePluginClient() :
{
char tmpFileBase[60];

srand(time(NULL));

sprintf(tmpFileBase, "/tmp/rplugin_crq_XXXXXX");
if (mkstemp(tmpFileBase) < 0) {
cleanup();
Expand Down Expand Up @@ -68,18 +71,13 @@ RemotePluginClient::RemotePluginClient() :
throw((std::string)"Failed to create FIFO");
}

sprintf(tmpFileBase, "/tmp/rplugin_shc_XXXXXX");
if (mkstemp(tmpFileBase) < 0) {
cleanup();
throw((std::string)"Failed to obtain temporary filename");
}
m_shmControlFileName = strdup(tmpFileBase);

m_shmControlFd = open(m_shmControlFileName, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
sprintf(tmpFileBase, "/dssi-vst-rplugin_shc_XXXXXX");
m_shmControlFd = shm_mkstemp(tmpFileBase);
if (m_shmControlFd < 0) {
cleanup();
throw((std::string)"Failed to open or create shared memory file");
}
m_shmControlFileName = strdup(tmpFileBase);
ftruncate(m_shmControlFd, sizeof(ShmControl));
m_shmControl = static_cast<ShmControl *>(mmap(0, sizeof(ShmControl), PROT_READ | PROT_WRITE, MAP_SHARED, m_shmControlFd, 0));
if (!m_shmControl) {
Expand All @@ -95,18 +93,13 @@ RemotePluginClient::RemotePluginClient() :
throw((std::string)"Failed to initialize shared memory semaphore");
}

sprintf(tmpFileBase, "/tmp/rplugin_shm_XXXXXX");
if (mkstemp(tmpFileBase) < 0) {
cleanup();
throw((std::string)"Failed to obtain temporary filename");
}
m_shmFileName = strdup(tmpFileBase);

m_shmFd = open(m_shmFileName, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
sprintf(tmpFileBase, "/dssi-vst-rplugin_shm_XXXXXX");
m_shmFd = shm_mkstemp(tmpFileBase);
if (m_shmFd < 0) {
cleanup();
throw((std::string)"Failed to open or create shared memory file");
}
m_shmFileName = strdup(tmpFileBase);
}

RemotePluginClient::~RemotePluginClient()
Expand Down Expand Up @@ -195,12 +188,12 @@ RemotePluginClient::cleanup()
m_controlResponseFileName = 0;
}
if (m_shmFileName) {
unlink(m_shmFileName);
shm_unlink(m_shmFileName);
free(m_shmFileName);
m_shmFileName = 0;
}
if (m_shmControlFileName) {
unlink(m_shmControlFileName);
shm_unlink(m_shmControlFileName);
free(m_shmControlFileName);
m_shmControlFileName = 0;
}
Expand Down
8 changes: 4 additions & 4 deletions remotepluginserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ RemotePluginServer::RemotePluginServer(std::string fileIdentifiers) :
}

bool b = false;
sprintf(tmpFileBase, "/tmp/rplugin_shc_%s",
sprintf(tmpFileBase, "/dssi-vst-rplugin_shc_%s",
fileIdentifiers.substr(12, 6).c_str());
m_shmControlFileName = strdup(tmpFileBase);

m_shmControlFd = open(m_shmControlFileName, O_RDWR);
m_shmControlFd = shm_open(m_shmControlFileName, O_RDWR, 0);
if (m_shmControlFd < 0) {
tryWrite(m_controlResponseFd, &b, sizeof(bool));
cleanup();
Expand All @@ -80,11 +80,11 @@ RemotePluginServer::RemotePluginServer(std::string fileIdentifiers) :
throw((std::string)"Failed to mmap shared memory file");
}

sprintf(tmpFileBase, "/tmp/rplugin_shm_%s",
sprintf(tmpFileBase, "/dssi-vst-rplugin_shm_%s",
fileIdentifiers.substr(18, 6).c_str());
m_shmFileName = strdup(tmpFileBase);

if ((m_shmFd = open(m_shmFileName, O_RDWR)) < 0) {
if ((m_shmFd = shm_open(m_shmFileName, O_RDWR, 0)) < 0) {
tryWrite(m_controlResponseFd, &b, sizeof(bool));
cleanup();
throw((std::string)"Failed to open shared memory file");
Expand Down

0 comments on commit 059098b

Please sign in to comment.