SHMEM: Fix various Linux and Windows problems
- Windows did not validate that the a segment size was correct. - Add shared memory object name to the management structure - Linux shared memory object names must start with a / - Linux umask setting to assign permissions - Add textual explanations for failure cases
This commit is contained in:
parent
4487646946
commit
91e4efbd59
1 changed files with 56 additions and 11 deletions
67
sim_fio.c
67
sim_fio.c
|
@ -418,32 +418,59 @@ struct SHMEM {
|
||||||
HANDLE hMapping;
|
HANDLE hMapping;
|
||||||
size_t shm_size;
|
size_t shm_size;
|
||||||
void *shm_base;
|
void *shm_base;
|
||||||
|
char *shm_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr)
|
t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr)
|
||||||
{
|
{
|
||||||
*shmem = (SHMEM *)calloc (1, sizeof(**shmem));
|
SYSTEM_INFO SysInfo;
|
||||||
|
t_bool AlreadyExists;
|
||||||
|
|
||||||
|
GetSystemInfo (&SysInfo);
|
||||||
|
*shmem = (SHMEM *)calloc (1, sizeof(**shmem));
|
||||||
if (*shmem == NULL)
|
if (*shmem == NULL)
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
|
(*shmem)->shm_name = (char *)calloc (1, 1 + strlen (name));
|
||||||
|
if ((*shmem)->shm_name == NULL) {
|
||||||
|
free (*shmem);
|
||||||
|
*shmem = NULL;
|
||||||
|
return SCPE_MEM;
|
||||||
|
}
|
||||||
|
strcpy ((*shmem)->shm_name, name);
|
||||||
(*shmem)->hMapping = INVALID_HANDLE_VALUE;
|
(*shmem)->hMapping = INVALID_HANDLE_VALUE;
|
||||||
(*shmem)->shm_size = size;
|
(*shmem)->shm_size = size;
|
||||||
(*shmem)->shm_base = NULL;
|
(*shmem)->shm_base = NULL;
|
||||||
(*shmem)->hMapping = CreateFileMappingA (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)size, name);
|
(*shmem)->hMapping = CreateFileMappingA (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE|SEC_COMMIT, 0, (DWORD)(size+SysInfo.dwPageSize), name);
|
||||||
if ((*shmem)->hMapping == INVALID_HANDLE_VALUE) {
|
if ((*shmem)->hMapping == INVALID_HANDLE_VALUE) {
|
||||||
|
DWORD LastError = GetLastError();
|
||||||
|
|
||||||
sim_shmem_close (*shmem);
|
sim_shmem_close (*shmem);
|
||||||
*shmem = NULL;
|
*shmem = NULL;
|
||||||
return SCPE_OPENERR;
|
return sim_messagef (SCPE_OPENERR, "Can't CreateFileMapping of a %u byte shared memory segment '%s' - LastError=0x%X\n", size, name, LastError);
|
||||||
}
|
}
|
||||||
|
AlreadyExists = (GetLastError () == ERROR_ALREADY_EXISTS);
|
||||||
(*shmem)->shm_base = MapViewOfFile ((*shmem)->hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
(*shmem)->shm_base = MapViewOfFile ((*shmem)->hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||||
if ((*shmem)->shm_base == NULL) {
|
if ((*shmem)->shm_base == NULL) {
|
||||||
|
DWORD LastError = GetLastError();
|
||||||
|
|
||||||
sim_shmem_close (*shmem);
|
sim_shmem_close (*shmem);
|
||||||
*shmem = NULL;
|
*shmem = NULL;
|
||||||
return SCPE_OPENERR;
|
return sim_messagef (SCPE_OPENERR, "Can't MapViewOfFile() of a %u byte shared memory segment '%s' - LastError=0x%X\n", size, name, LastError);
|
||||||
}
|
}
|
||||||
|
if (AlreadyExists) {
|
||||||
|
if (*((DWORD *)((*shmem)->shm_base)) == 0)
|
||||||
|
Sleep (50);
|
||||||
|
if (*((DWORD *)((*shmem)->shm_base)) != (DWORD)size) {
|
||||||
|
DWORD SizeFound = *((DWORD *)((*shmem)->shm_base));
|
||||||
|
sim_shmem_close (*shmem);
|
||||||
|
*shmem = NULL;
|
||||||
|
return sim_messagef (SCPE_OPENERR, "Shared Memory segment '%s' is %u bytes instead of %d\n", name, SizeFound, (int)size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*((DWORD *)((*shmem)->shm_base)) = (DWORD)size; /* Save Size in first page */
|
||||||
|
|
||||||
*addr = (*shmem)->shm_base;
|
*addr = ((char *)(*shmem)->shm_base + SysInfo.dwPageSize); /* Point to the second paget for data */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,6 +482,7 @@ if (shmem->shm_base != NULL)
|
||||||
UnmapViewOfFile (shmem->shm_base);
|
UnmapViewOfFile (shmem->shm_base);
|
||||||
if (shmem->hMapping != INVALID_HANDLE_VALUE)
|
if (shmem->hMapping != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle (shmem->hMapping);
|
CloseHandle (shmem->hMapping);
|
||||||
|
free (shmem->shm_name);
|
||||||
free (shmem);
|
free (shmem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,26 +582,40 @@ struct SHMEM {
|
||||||
int shm_fd;
|
int shm_fd;
|
||||||
size_t shm_size;
|
size_t shm_size;
|
||||||
void *shm_base;
|
void *shm_base;
|
||||||
|
char *shm_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr)
|
t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_SHM_OPEN
|
#ifdef HAVE_SHM_OPEN
|
||||||
*shmem = (SHMEM *)calloc (1, sizeof(**shmem));
|
*shmem = (SHMEM *)calloc (1, sizeof(**shmem));
|
||||||
|
mode_t orig_mask;
|
||||||
|
|
||||||
*addr = NULL;
|
*addr = NULL;
|
||||||
if (*shmem == NULL)
|
if (*shmem == NULL)
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
|
(*shmem)->shm_name = (char *)calloc (1, 1 + strlen (name) + ((*name != '/') ? 1 : 0));
|
||||||
|
if ((*shmem)->shm_name == NULL) {
|
||||||
|
free (*shmem);
|
||||||
|
*shmem = NULL;
|
||||||
|
return SCPE_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf ((*shmem)->shm_name, "%s%s", ((*name != '/') ? "/" : ""), name);
|
||||||
(*shmem)->shm_base = MAP_FAILED;
|
(*shmem)->shm_base = MAP_FAILED;
|
||||||
(*shmem)->shm_size = size;
|
(*shmem)->shm_size = size;
|
||||||
(*shmem)->shm_fd = shm_open (name, O_RDWR, 0);
|
(*shmem)->shm_fd = shm_open ((*shmem)->shm_name, O_RDWR, 0);
|
||||||
if ((*shmem)->shm_fd == -1) {
|
if ((*shmem)->shm_fd == -1) {
|
||||||
(*shmem)->shm_fd = shm_open (name, O_CREAT | O_RDWR, 0660);
|
int last_errno;
|
||||||
|
|
||||||
|
orig_mask = umask (0000);
|
||||||
|
(*shmem)->shm_fd = shm_open ((*shmem)->shm_name, O_CREAT | O_RDWR, 0660);
|
||||||
|
last_errno = errno;
|
||||||
|
umask (orig_mask); /* Restore original mask */
|
||||||
if ((*shmem)->shm_fd == -1) {
|
if ((*shmem)->shm_fd == -1) {
|
||||||
sim_shmem_close (*shmem);
|
sim_shmem_close (*shmem);
|
||||||
*shmem = NULL;
|
*shmem = NULL;
|
||||||
return SCPE_OPENERR;
|
return sim_messagef (SCPE_OPENERR, "Can't shm_open() a %d byte shared memory segment '%s' - errno=%d - %s\n", (int)size, name, last_errno, strerror (last_errno));
|
||||||
}
|
}
|
||||||
if (ftruncate((*shmem)->shm_fd, size)) {
|
if (ftruncate((*shmem)->shm_fd, size)) {
|
||||||
sim_shmem_close (*shmem);
|
sim_shmem_close (*shmem);
|
||||||
|
@ -588,14 +630,16 @@ else {
|
||||||
(statb.st_size != (*shmem)->shm_size)) {
|
(statb.st_size != (*shmem)->shm_size)) {
|
||||||
sim_shmem_close (*shmem);
|
sim_shmem_close (*shmem);
|
||||||
*shmem = NULL;
|
*shmem = NULL;
|
||||||
return SCPE_OPENERR;
|
return sim_messagef (SCPE_OPENERR, "Shared Memory segment '%s' is %d bytes instead of %d\n", name, (int)(statb.st_size), (int)size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(*shmem)->shm_base = mmap(NULL, (*shmem)->shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, (*shmem)->shm_fd, 0);
|
(*shmem)->shm_base = mmap(NULL, (*shmem)->shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, (*shmem)->shm_fd, 0);
|
||||||
if ((*shmem)->shm_base == MAP_FAILED) {
|
if ((*shmem)->shm_base == MAP_FAILED) {
|
||||||
|
int last_errno = errno;
|
||||||
|
|
||||||
sim_shmem_close (*shmem);
|
sim_shmem_close (*shmem);
|
||||||
*shmem = NULL;
|
*shmem = NULL;
|
||||||
return SCPE_OPENERR;
|
return sim_messagef (SCPE_OPENERR, "Shared Memory '%s' mmap() failed. errno=%d - %s\n", name, last_errno, strerror (last_errno));
|
||||||
}
|
}
|
||||||
*addr = (*shmem)->shm_base;
|
*addr = (*shmem)->shm_base;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -612,6 +656,7 @@ if (shmem->shm_base != MAP_FAILED)
|
||||||
munmap (shmem->shm_base, shmem->shm_size);
|
munmap (shmem->shm_base, shmem->shm_size);
|
||||||
if (shmem->shm_fd != -1)
|
if (shmem->shm_fd != -1)
|
||||||
close (shmem->shm_fd);
|
close (shmem->shm_fd);
|
||||||
|
free (shmem->shm_name);
|
||||||
free (shmem);
|
free (shmem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue