@@ -341,6 +341,7 @@ static bool check_missing_real(const char *name, bool missing)
341341#define CHECK_MISSING_REAL (name ) \
342342 check_missing_real(#name, (NULL == real_##name))
343343
344+ static pthread_mutex_t initialized_once_mutex ;
344345static pthread_once_t initialized_once_control = PTHREAD_ONCE_INIT ;
345346
346347/* prototypes */
@@ -715,12 +716,59 @@ static void ft_shm_destroy(void)
715716 }
716717}
717718
719+ static void ft_initialize_errorcheck_mutex (pthread_mutex_t * mutex )
720+ {
721+ pthread_mutexattr_t attr ;
722+ int ret = pthread_mutexattr_init (& attr );
723+ if (ret != 0 ) {
724+ fprintf (stderr , "libfaketime: failed to initialize mutex attribute: %d\n" , ret );
725+ exit (-1 );
726+ }
727+ ret = pthread_mutexattr_settype (& attr , PTHREAD_MUTEX_ERRORCHECK );
728+ if (ret != 0 ) {
729+ fprintf (stderr , "libfaketime: failed to set errorcheck mutex attribute: %d\n" , ret );
730+ exit (-1 );
731+ }
732+ ret = pthread_mutex_init (mutex , & attr );
733+ if (ret != 0 ) {
734+ fprintf (stderr , "libfaketime: failed to initialize errorcheck mutex: %d\n" , ret );
735+ exit (-1 );
736+ }
737+ }
738+
739+ static void ft_init_once_generic (bool * init_done , pthread_once_t * once_control , pthread_mutex_t * mutex , void (* init_mutex_cb )(void ), void (* initializer_cb )(void ))
740+ {
741+ pthread_once (once_control , init_mutex_cb );
742+ int ret = pthread_mutex_lock (mutex );
743+ if (ret == 0 ) {
744+ if (!* init_done ) {
745+ // Set this to `true` before we call the initialisation; the effect is that
746+ // recursive calls to `ftpl_init` or `ft_shm_really_init` will be suppressed.
747+ // If anything that they use calls back to a time function
748+ // it will get some not- or partially-set-up faketime state.
749+ // We are betting that that's good enough.
750+ // (Empirically, on some platforms the shm functions call `statx`;
751+ // we think the timestamps in that call probably don't matter.)
752+ * init_done = true;
753+ initializer_cb ();
754+ }
755+ pthread_mutex_unlock (mutex );
756+ }
757+ }
758+
759+ static pthread_mutex_t ft_shm_initialized_once_mutex ;
718760static pthread_once_t ft_shm_initialized_once_control = PTHREAD_ONCE_INIT ;
719761
762+ static void ft_shm_init_mutex (void )
763+ {
764+ ft_initialize_errorcheck_mutex (& ft_shm_initialized_once_mutex );
765+ }
766+
720767static void ft_shm_really_init (void );
721768static void ft_shm_init (void )
722769{
723- pthread_once (& ft_shm_initialized_once_control , ft_shm_really_init );
770+ static bool init_done = false;
771+ ft_init_once_generic (& init_done , & ft_shm_initialized_once_control , & ft_shm_initialized_once_mutex , & ft_shm_init_mutex , & ft_shm_really_init );
724772}
725773
726774static void ft_shm_really_init (void )
@@ -3256,8 +3304,14 @@ static void ftpl_really_init(void)
32563304 dont_fake = dont_fake_final ;
32573305}
32583306
3307+ static void init_initialized_once_mutex (void )
3308+ {
3309+ ft_initialize_errorcheck_mutex (& initialized_once_mutex );
3310+ }
3311+
32593312inline static void ftpl_init (void ) {
3260- pthread_once (& initialized_once_control , ftpl_really_init );
3313+ static bool init_done = false;
3314+ ft_init_once_generic (& init_done , & initialized_once_control , & initialized_once_mutex , & init_initialized_once_mutex , & ftpl_really_init );
32613315}
32623316
32633317void * ft_dlvsym (void * handle , const char * symbol , const char * version ,
0 commit comments