Skip to content

Commit c154de1

Browse files
authored
changes in shmmap (#1865)
1 parent 5d4e0ca commit c154de1

File tree

2 files changed

+57
-10
lines changed

2 files changed

+57
-10
lines changed

src/shm.cpp

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,17 @@ enum { BYTE=0,COMPLEX,DCOMPLEX,DOUBLE,FLOAT,INTEGER,L64,LONG,UINT,UL64,ULONG, DI
3333
//atom size of all types and names
3434
static const std::string atomName[16]={"UNDEFINED","BYTE","INT","LONG","FLOAT","DOUBLE","COMPLEX","STRING","STRUCT","DCOMPLEX","POINTER","OBJREF","UINT","ULONG","LONG64","ULONG64"};
3535
static const int atomSize[16]={0,1,2,4,4,8,8,0,0,16,0,0,2,4,8,8};
36-
namespace lib {
36+
static bool atexit_already_done = false;
37+
38+
void AddToAtexit() {
39+
if (!atexit_already_done) {
40+
atexit_already_done = true;
41+
atexit(lib::TidySharedAtGDLExit);
42+
}
43+
}
3744

45+
namespace lib {
46+
3847
bool get_shm_common_keywords(EnvT* e, std::string &segmentName, dimension & dim, int & type) {
3948
SizeT np = e->NParam(0);
4049
if (np != 0) e->AssureStringScalarPar(0, segmentName);
@@ -145,12 +154,10 @@ namespace lib {
145154
//reinterpret OS_HANDLE
146155
DLong sysv_handle=0;
147156
if (doOsHandle) { //must exist and be useable
148-
e->AssureLongScalarKW(OS_HANDLE,sysv_handle);
149-
int shmflg=all_perms;
150-
key_t handle=sysv_handle;
151-
sysv_hdle=shmget(handle,total_length,shmflg);
152-
if (sysv_hdle ==-1) e->Throw("SYSV Shared Memory Segment " + i2s(sysv_handle) + " attach failed, reason: " + std::string(strerror(errno)) + ".");
153-
} else {
157+
e->AssureLongScalarKW(OS_HANDLE,sysv_hdle); //handle must be sysv_hdle
158+
destroy_segment = false;
159+
} else { // a creation
160+
destroy_segment = true;
154161
int shmflg=IPC_CREAT|all_perms;
155162
key_t handle=0;
156163
sysv_hdle=shmget(handle,total_length,shmflg);
@@ -190,9 +197,13 @@ namespace lib {
190197
if (status != 0) e->Throw("Shared Memory Segment " + segmentName + " creation failed (size), reason: " + std::string(strerror(errno)) + ".");
191198
//segment is destroyable on exit unless 'destroy_segment' is set to 0
192199
destroy_segment = true;
193-
if (e->KeywordPresentAndDefined(DESTROY_SEGMENT)) destroy_segment = e->KeywordSet(DESTROY_SEGMENT);
200+
} else { //exist:
201+
destroy_segment = false;
194202
}
195203
}
204+
//DESTROY_SEGMENT modifies default behaviour
205+
if (e->KeywordPresentAndDefined(DESTROY_SEGMENT)) destroy_segment = e->KeywordSet(DESTROY_SEGMENT);
206+
if (destroy_segment) AddToAtexit();
196207
//now, exist or not, we define only the requested memory mapping size "length".
197208
void* mapAddress=NULL;
198209
if (sysv) {
@@ -247,7 +258,12 @@ namespace lib {
247258
if (((*i).second.flags & USE_SYSV) == USE_SYSV) {
248259
int result=shmdt((*i).second.mapped_address);
249260
if (result ==-1) e->Throw("SYSV Shared Memory Segment " + segmentName + " Unmapping unsucessfull, reason: "+ std::string(strerror(errno))+".");
261+
if (((*i).second.flags & DESTROY_SEGMENT_ON_UNMAP)==DESTROY_SEGMENT_ON_UNMAP) {
262+
int shmid=0;
263+
if (sscanf((*i).second.osHandle.c_str(),"%i",&shmid)==1) shmctl(shmid, IPC_RMID, NULL);
264+
}
250265
} else {
266+
msync((*i).second.mapped_address,(*i).second.length, MS_ASYNC); //msync is recommended even if probably overkill on linux since 2.6.19
251267
int result=munmap((*i).second.mapped_address,(*i).second.length); //unmap
252268
if (result !=0) e->Throw("Shared Memory Segment " + segmentName + " Unmapping unsucessfull, reason: "+ std::string(strerror(errno))+".");
253269
if (((*i).second.flags & DESTROY_SEGMENT_ON_UNMAP)==DESTROY_SEGMENT_ON_UNMAP) shm_unlink((*i).second.osHandle.c_str());
@@ -386,7 +402,7 @@ namespace lib {
386402
}
387403
return;
388404
}
389-
//called from system when deleting a mapped variable
405+
//called from system when deleting a mapped variable.
390406
void shm_unreference(BaseGDL* var){
391407
void* pointer=var->DataAddr(); //the mapped address
392408
for (shmListIter i=shmList.begin(); i!=shmList.end(); ++i) {
@@ -399,7 +415,12 @@ namespace lib {
399415
if (((*i).second.flags & USE_SYSV) == USE_SYSV) {
400416
int result = shmdt((*i).second.mapped_address);
401417
if (result == -1) Warning("SYSV Shared Memory Segment " + (*i).first + " Unmapping unsucessfull after deleting last mapped variable, reason: " + std::string(strerror(errno)) + ".");
418+
if (((*i).second.flags & DESTROY_SEGMENT_ON_UNMAP) == DESTROY_SEGMENT_ON_UNMAP) {
419+
int shmid = 0;
420+
if (sscanf((*i).second.osHandle.c_str(), "%i", &shmid) == 1) shmctl(shmid, IPC_RMID, NULL);
421+
}
402422
} else {
423+
msync((*i).second.mapped_address,(*i).second.length, MS_ASYNC); //msync is recommended even if probably overkill on linux since 2.6.19
403424
int result = munmap((*i).second.mapped_address, (*i).second.length); //unmap
404425
if (result != 0) Warning("Shared Memory Segment " + (*i).first + " Unmapping unsucessfull after deleting last mapped variable, reason: " + std::string(strerror(errno)) + ".");
405426
if (((*i).second.flags & DESTROY_SEGMENT_ON_UNMAP) == DESTROY_SEGMENT_ON_UNMAP) shm_unlink((*i).second.osHandle.c_str());
@@ -410,5 +431,31 @@ namespace lib {
410431
}
411432
}
412433
}
434+
void shm_tidy() {
435+
for (shmListIter i = shmList.begin(); i != shmList.end(); ++i) {
436+
if (((*i).second.flags & USE_SYSV) == USE_SYSV) {
437+
int result = shmdt((*i).second.mapped_address);
438+
if (result == -1) Warning("SYSV Shared Memory Segment " + (*i).first + " Unmapping unsucessfull after deleting last mapped variable, reason: " + std::string(strerror(errno)) + ".");
439+
if (((*i).second.flags & DESTROY_SEGMENT_ON_UNMAP) == DESTROY_SEGMENT_ON_UNMAP) {
440+
int shmid = 0;
441+
if (sscanf((*i).second.osHandle.c_str(), "%i", &shmid) == 1) shmctl(shmid, IPC_RMID, NULL);
442+
}
443+
} else {
444+
msync((*i).second.mapped_address, (*i).second.length, MS_ASYNC); //msync is recommended even if probably overkill on linux since 2.6.19
445+
int result = munmap((*i).second.mapped_address, (*i).second.length); //unmap
446+
if (result != 0) Warning("Shared Memory Segment " + (*i).first + " Unmapping unsucessfull after deleting last mapped variable, reason: " + std::string(strerror(errno)) + ".");
447+
if (((*i).second.flags & DESTROY_SEGMENT_ON_UNMAP) == DESTROY_SEGMENT_ON_UNMAP) shm_unlink((*i).second.osHandle.c_str());
448+
}
449+
}
450+
}
451+
452+
void TidySharedAtGDLExit()
453+
{
454+
//remove shared mem mappings that need to be removed according to permissions etc.
455+
#ifndef _WIN32
456+
shm_tidy();
457+
#endif
458+
}
459+
413460
} // namespace
414461
#endif

src/shm.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ namespace lib {
4949
void shmunmap_pro(EnvT* e);
5050
BaseGDL* shmvar_fun(EnvT* e);
5151
BaseGDL* shmdebug_fun(EnvT* e);
52-
52+
void TidySharedAtGDLExit();
5353
} // namespace
5454

5555
#endif

0 commit comments

Comments
 (0)