@@ -33,8 +33,17 @@ enum { BYTE=0,COMPLEX,DCOMPLEX,DOUBLE,FLOAT,INTEGER,L64,LONG,UINT,UL64,ULONG, DI
33
33
// atom size of all types and names
34
34
static const std::string atomName[16 ]={" UNDEFINED" ," BYTE" ," INT" ," LONG" ," FLOAT" ," DOUBLE" ," COMPLEX" ," STRING" ," STRUCT" ," DCOMPLEX" ," POINTER" ," OBJREF" ," UINT" ," ULONG" ," LONG64" ," ULONG64" };
35
35
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
+ }
37
44
45
+ namespace lib {
46
+
38
47
bool get_shm_common_keywords (EnvT* e, std::string &segmentName, dimension & dim, int & type) {
39
48
SizeT np = e->NParam (0 );
40
49
if (np != 0 ) e->AssureStringScalarPar (0 , segmentName);
@@ -145,12 +154,10 @@ namespace lib {
145
154
// reinterpret OS_HANDLE
146
155
DLong sysv_handle=0 ;
147
156
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 ;
154
161
int shmflg=IPC_CREAT|all_perms;
155
162
key_t handle=0 ;
156
163
sysv_hdle=shmget (handle,total_length,shmflg);
@@ -190,9 +197,13 @@ namespace lib {
190
197
if (status != 0 ) e->Throw (" Shared Memory Segment " + segmentName + " creation failed (size), reason: " + std::string (strerror (errno)) + " ." );
191
198
// segment is destroyable on exit unless 'destroy_segment' is set to 0
192
199
destroy_segment = true ;
193
- if (e->KeywordPresentAndDefined (DESTROY_SEGMENT)) destroy_segment = e->KeywordSet (DESTROY_SEGMENT);
200
+ } else { // exist:
201
+ destroy_segment = false ;
194
202
}
195
203
}
204
+ // DESTROY_SEGMENT modifies default behaviour
205
+ if (e->KeywordPresentAndDefined (DESTROY_SEGMENT)) destroy_segment = e->KeywordSet (DESTROY_SEGMENT);
206
+ if (destroy_segment) AddToAtexit ();
196
207
// now, exist or not, we define only the requested memory mapping size "length".
197
208
void * mapAddress=NULL ;
198
209
if (sysv) {
@@ -247,7 +258,12 @@ namespace lib {
247
258
if (((*i).second .flags & USE_SYSV) == USE_SYSV) {
248
259
int result=shmdt ((*i).second .mapped_address );
249
260
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
+ }
250
265
} 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
251
267
int result=munmap ((*i).second .mapped_address ,(*i).second .length ); // unmap
252
268
if (result !=0 ) e->Throw (" Shared Memory Segment " + segmentName + " Unmapping unsucessfull, reason: " + std::string (strerror (errno))+" ." );
253
269
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 {
386
402
}
387
403
return ;
388
404
}
389
- // called from system when deleting a mapped variable
405
+ // called from system when deleting a mapped variable.
390
406
void shm_unreference (BaseGDL* var){
391
407
void * pointer=var->DataAddr (); // the mapped address
392
408
for (shmListIter i=shmList.begin (); i!=shmList.end (); ++i) {
@@ -399,7 +415,12 @@ namespace lib {
399
415
if (((*i).second .flags & USE_SYSV) == USE_SYSV) {
400
416
int result = shmdt ((*i).second .mapped_address );
401
417
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
+ }
402
422
} 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
403
424
int result = munmap ((*i).second .mapped_address , (*i).second .length ); // unmap
404
425
if (result != 0 ) Warning (" Shared Memory Segment " + (*i).first + " Unmapping unsucessfull after deleting last mapped variable, reason: " + std::string (strerror (errno)) + " ." );
405
426
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 {
410
431
}
411
432
}
412
433
}
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
+
413
460
} // namespace
414
461
#endif
0 commit comments