@@ -386,19 +386,16 @@ _get_constant_semlock(PyObject *self)
386386 return 0 ;
387387 PyTypeObject * semlock_type = Py_TYPE (self );
388388 if (semlock_type == NULL ) {
389- puts ("Cannot get type of self" );
390389 return -1 ;
391390 }
392391
393392 PyObject * module = PyType_GetModule (semlock_type );
394393 if (module == NULL ) {
395- puts ("Cannot get type of self" );
396394 return -1 ;
397395 }
398396
399397 PyObject * py_name = PyObject_GetAttrString (module , "_MACOSX_SHAREDMEM_NAME" );
400398 if (py_name == NULL ) {
401- puts ("Cannot get shared memory name from module" );
402399 Py_DECREF (py_name );
403400 return -1 ;
404401 }
@@ -481,13 +478,13 @@ release_lock(SEM_HANDLE handle)
481478}
482479
483480static int
484- exists_lock (SEM_HANDLE handle )
481+ exist_lock (SEM_HANDLE handle )
485482{
486483 int res = -1 ;
487484 int err = 0 ;
488485
489486 if (handle == NULL || handle == SEM_FAILED ) {
490- DEBUG_PID_FUNC ("0" , handle , (unsigned long )errno , "Sem never createt " );
487+ DEBUG_PID_FUNC ("0" , handle , (unsigned long )errno , "Sem never created " );
491488 shm_semlock_counters .state_this = THIS_NOT_OPEN ;
492489 return 0 ;
493490 }
@@ -656,32 +653,28 @@ Shared memory management
656653*/
657654
658655static int
659- delete_shm_semlock_counters (int lock_shm )
656+ delete_shm_semlock_counters (void )
660657{
661- int n_sems = 0 ;
662-
658+ int res = - 1 ;
663659 if (shm_semlock_counters .handle_glock != SEM_FAILED &&
664660 shm_semlock_counters .state_this == THIS_AVAILABLE ) {
665661
666- n_sems = shm_semlock_counters .header -> n_semlocks ;
667- if (n_sems == 0 ) {
668- DEBUG_PID_FUNC (shm_semlock_counters .name_shm , shm_semlock_counters .handle_shm ,
669- 0 , "remove glock and shared mem" );
670- munmap (shm_semlock_counters .header ,
671- shm_semlock_counters .header -> size_shm );
672- if (shm_semlock_counters .handle_shm > 0 ) {
673- close (shm_semlock_counters .handle_shm );
674- shm_semlock_counters .handle_shm = (MEMORY_HANDLE )0 ;
675- }
676- Py_BEGIN_ALLOW_THREADS
677- shm_unlink (shm_semlock_counters .name_shm );
678- Py_END_ALLOW_THREADS
679- shm_semlock_counters .header = NULL ;
680- shm_semlock_counters .counters = NULL ;
681- shm_semlock_counters .state_this = THIS_CLOSED ;
662+ DEBUG_PID_FUNC (shm_semlock_counters .name_shm , shm_semlock_counters .handle_shm ,
663+ 0 , "remove glock and shared mem" );
664+ res = munmap (shm_semlock_counters .header ,
665+ shm_semlock_counters .header -> size_shm );
666+ if (shm_semlock_counters .handle_shm > 0 ) {
667+ res = close (shm_semlock_counters .handle_shm );
668+ shm_semlock_counters .handle_shm = (MEMORY_HANDLE )0 ;
682669 }
670+ Py_BEGIN_ALLOW_THREADS
671+ res = shm_unlink (shm_semlock_counters .name_shm );
672+ Py_END_ALLOW_THREADS
673+ shm_semlock_counters .header = NULL ;
674+ shm_semlock_counters .counters = NULL ;
675+ shm_semlock_counters .state_this = THIS_CLOSED ;
683676 }
684- return n_sems ;
677+ return res ;
685678}
686679
687680static int
@@ -911,10 +904,9 @@ Name is unique and create from SemLock python class.
911904static char * gh_name = "_gh125828" ;
912905
913906static char *
914- _build_sem_name (char * buf , const char * name )
907+ _build_mutex_name (char * buf , int size , const char * name )
915908{
916- strcpy (buf , name );
917- strcat (buf , gh_name );
909+ PyOS_snprintf (buf , size , "%s%s" , name , gh_name );
918910 return buf ;
919911}
920912
@@ -994,13 +986,14 @@ connect_counter(SemLockObject *self)
994986Create a new CounterObject for a Semaphore, from `SemLock_Impl`.
995987*/
996988static CounterObject *
997- new_counter (SemLockObject * self , const char * name , int value )
989+ new_counter (SemLockObject * self , const char * name , int value , int unlink )
998990{
999991 CounterObject * counter = _search_counter_free_slot ();
1000992 if (counter ) {
1001993 strcpy (counter -> sem_name , name );
1002994 counter -> internal_value = value ;
1003995 counter -> n_instances = 0 ;
996+ counter -> unlink = unlink ;
1004997 counter -> ctimestamp = time (NULL );
1005998
1006999 // Update header.
@@ -1022,14 +1015,12 @@ remove_counter(CounterObject *counter)
10221015{
10231016 int res = -1 ;
10241017 DEBUG_PID_FUNC (counter -> sem_name , 0 , counter , "" );
1025-
10261018 memset (counter , 0 , sizeof (CounterObject ));
10271019 -- shm_semlock_counters .header -> n_semlocks ;
1028- /* --- */
1029- if (shm_semlock_counters .header -> n_semlocks == 0 ) {
1030- res = delete_shm_semlock_counters (false );
1020+
1021+ if (! shm_semlock_counters .header -> n_semlocks ) {
1022+ res = delete_shm_semlock_counters ();
10311023 }
1032- /* -- */
10331024 return res ;
10341025}
10351026
@@ -1314,16 +1305,9 @@ _multiprocessing_SemLock_impl(PyTypeObject *type, int kind, int value,
13141305 semlock = _SemLockObject_CAST (result );
13151306 if (ISSEMAPHORE (semlock )) {
13161307 PyMutex_Lock (& shm_semlock_counters .shm_counters_mutex );
1317- if (!exists_lock (shm_semlock_counters .handle_glock ) ||
1308+ if (!exist_lock (shm_semlock_counters .handle_glock ) ||
13181309 shm_semlock_counters .state_this != THIS_AVAILABLE ) {
1319- if (!strlen (name_shm )) {
1320- if (_get_constant_semlock (result ) < 0 ) {
1321- PyMutex_Unlock (& shm_semlock_counters .shm_counters_mutex );
1322- goto failure ;
1323- }
1324- DEBUG_PID_FUNC (name_shm , 0 , counter , "SHM NAME" );
1325- DEBUG_PID_FUNC (name_glock , 0 , counter , "LOCK NAME" );
1326- }
1310+
13271311 if (create_shm_semlock_counters (name ) < 0 ) {
13281312// if (_create_shm_semlock_counters(name) < 0) {
13291313 PyMutex_Unlock (& shm_semlock_counters .shm_counters_mutex );
@@ -1335,9 +1319,9 @@ _multiprocessing_SemLock_impl(PyTypeObject *type, int kind, int value,
13351319 // error is set in ACQUIRE/RELEASE_* macros.
13361320 if (!ACQUIRE_GLOCK ) // error set in acquire_lock function
13371321 goto failure ;
1338- handle_mutex = SEM_CREATE (_build_sem_name (mutex_name , name ), 1 , 1 );
1322+ handle_mutex = SEM_CREATE (_build_mutex_name (mutex_name , SIZE_MUTEX_NAME , name ), 1 , 1 );
13391323 if (handle_mutex != SEM_FAILED ) {
1340- counter = new_counter (semlock , name , value );
1324+ counter = new_counter (semlock , name , value , unlink );
13411325 if (counter ) {
13421326 semlock -> handle_mutex = handle_mutex ;
13431327 semlock -> counter = counter ;
@@ -1448,14 +1432,8 @@ _multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle,
14481432 semlock = _SemLockObject_CAST (result );
14491433 if (ISSEMAPHORE (semlock )) {
14501434 PyMutex_Lock (& shm_semlock_counters .shm_counters_mutex );
1451- if (!exists_lock (shm_semlock_counters .handle_glock ) ||
1435+ if (!exist_lock (shm_semlock_counters .handle_glock ) ||
14521436 shm_semlock_counters .state_this != THIS_AVAILABLE ) {
1453- if (!strlen (name_shm )) {
1454- if (_get_constant_semlock (result ) < 0 ) {
1455- PyMutex_Unlock (& shm_semlock_counters .shm_counters_mutex );
1456- goto failure ;
1457- }
1458- }
14591437 if (create_shm_semlock_counters (name ) < 0 ) {
14601438// if (_connect_shm_semlock_counters(name) < 0) {
14611439 PyMutex_Unlock (& shm_semlock_counters .shm_counters_mutex );
@@ -1468,7 +1446,7 @@ _multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle,
14681446 goto failure ;
14691447 }
14701448 // error is set in ACQUIRE/RELEASE_* macros.
1471- handle_mutex = sem_open (_build_sem_name (mutex_name , name ), 0 );
1449+ handle_mutex = sem_open (_build_mutex_name (mutex_name , SIZE_MUTEX_NAME , name ), 0 );
14721450 if (handle_mutex != SEM_FAILED ) {
14731451 counter = connect_counter (semlock );
14741452 if (counter ) {
@@ -1503,8 +1481,8 @@ _multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle,
15031481 }
15041482 if (semlock -> handle_mutex != SEM_FAILED ) {
15051483 SEM_CLOSE (semlock -> handle_mutex );
1506- }
15071484
1485+ }
15081486 PyObject_GC_UnTrack (semlock );
15091487 type -> tp_free (semlock );
15101488 Py_DECREF (type );
@@ -1529,27 +1507,35 @@ semlock_dealloc(SemLockObject* self)
15291507 }
15301508
15311509#ifdef HAVE_BROKEN_SEM_GETVALUE
1532- int res = -1 ;
15331510 if (ISSEMAPHORE (self )) {
1511+ /*
1512+ In "forkserver" and "fork" start method, there are as many calls to
1513+ semlock_impl as calls to semlock_dealloc
1514+ In "spawn" start method, there are as calls to semlock_dealloc as
1515+ calls to semlock_impl plus calls to semlock_rebuild.
1516+ Here, it's not possible to known to teh real start method.
1517+ So we have to search if sempahore already exists yet.
1518+ */
1519+ int n_opened_sems = -1 ;
1520+ CounterObject * counter = NULL ;
1521+
15341522 if (self -> handle_mutex != SEM_FAILED ) {
15351523 SEM_CLOSE (self -> handle_mutex );
15361524 }
1537-
1538- if (ACQUIRE_GLOCK ) {
1539- DEBUG_PID_FUNC (self -> name , self -> handle_mutex , self -> counter , "" );
1540- if (self -> counter ) {
1541- DEBUG_PID_FUNC (self -> name , self -> handle_mutex , self -> counter , "decref counter" );
1542- -- self -> counter -> n_instances ;
1543- if (!self -> counter -> n_instances ) {
1544- res = remove_counter (self -> counter );
1545- self -> counter = NULL ;
1546- }
1547- }
1525+ DEBUG_PID_FUNC (self -> name , self -> handle , self -> counter , "handle mutex closed" );
1526+
1527+ if (EXIST_GLOCK && ACQUIRE_GLOCK ) {
1528+ DEBUG_PID_FUNC (self -> name , self -> handle_mutex , self -> counter , "unlink is one" );
1529+ if (self -> counter -> unlink == 1 ) {
1530+ n_opened_sems = remove_counter (self -> counter );
1531+ DEBUG_PID_FUNC (self -> name , self -> handle_mutex , self -> counter , "remove counter" );
1532+ }
15481533 RELEASE_GLOCK ;
1534+ if (n_opened_sems == 0 ) {
1535+ delete_glock ();
1536+ }
15491537 }
1550- if (!res ) {
1551- delete_glock ();
1552- }
1538+ self -> counter = NULL ;
15531539 }
15541540#endif /* HAVE_BROKEN_SEM_GETVALUE */
15551541
@@ -1780,7 +1766,7 @@ PyType_Spec _PyMp_SemLockType_spec = {
17801766 * Function to unlink semaphore names
17811767 */
17821768
1783- PyObject *
1769+ PyObject *
17841770_PyMp_sem_unlink (const char * name )
17851771{
17861772 if (SEM_UNLINK (name ) < 0 ) {
@@ -1790,9 +1776,52 @@ _PyMp_sem_unlink(const char *name)
17901776
17911777#ifdef HAVE_BROKEN_SEM_GETVALUE
17921778 char mutex_name [SIZE_MUTEX_NAME ];
1793-
1794- // Could failed if this not a semaphore
1795- SEM_UNLINK (_build_sem_name (mutex_name , name ));
1779+ CounterObject * counter = NULL ;
1780+ int n_opened_sems = -1 ;
1781+
1782+ if (SEM_UNLINK (_build_mutex_name (mutex_name , SIZE_MUTEX_NAME , name )) == 0 ) {
1783+ /*
1784+ So the only place where we could set unlink flag to 1 is there because this function is called
1785+ only per semaphore.
1786+ Note that in "fork" start method, this function is never called, unlink flag is always set to 0.
1787+ */
1788+ if (EXIST_GLOCK && ACQUIRE_GLOCK ) {
1789+ counter = _search_counter_from_sem_name (name );
1790+ if (counter ) {
1791+ DEBUG_PID_FUNC (name , 0 , counter , "unlink sem" );
1792+ n_opened_sems = remove_counter (counter );
1793+ }
1794+ RELEASE_GLOCK ;
1795+ if (!n_opened_sems ) {
1796+ delete_glock ();
1797+ }
1798+ }
1799+ /*
1800+ if (EXIST_GLOCK && ACQUIRE_GLOCK) {
1801+ counter = _search_counter_from_sem_name(name);
1802+ if (counter) {
1803+ DEBUG_PID_FUNC(name, 0, counter, "set unlink to 1");
1804+ counter->unlink = 1;
1805+ }
1806+ RELEASE_GLOCK;
1807+ }
1808+ */
1809+ /*
1810+ if (EXIST_GLOCK && ACQUIRE_GLOCK) {
1811+ puts("unlink sem, search counter and remove it");
1812+ counter = _search_counter_from_sem_name(name);
1813+ if (counter) {
1814+ DEBUG_PID_FUNC(name, 0, counter, "unlink sem");
1815+ n_opened_sems = remove_counter(counter);
1816+ puts("unlink sem, removed");
1817+ }
1818+ RELEASE_GLOCK;
1819+ if (!n_opened_sems) {
1820+ delete_glock();
1821+ }
1822+ }
1823+ */
1824+ }
17961825#endif /* HAVE_BROKEN_SEM_GETVALUE */
17971826
17981827 Py_RETURN_NONE ;
0 commit comments