guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 01/01: 'readdir' no longer deadlocks upon error.


From: Ludovic Courtès
Subject: [Guile-commits] 01/01: 'readdir' no longer deadlocks upon error.
Date: Fri, 17 Nov 2017 17:09:56 -0500 (EST)

civodul pushed a commit to branch stable-2.2
in repository guile.

commit 187655cedb42cc4b01088179649b02295cd35260
Author: Ludovic Courtès <address@hidden>
Date:   Fri Nov 17 23:05:53 2017 +0100

    'readdir' no longer deadlocks upon error.
    
    If 'readdir' returned an error, we'd call SCM_SYSERROR, which would try
    to acquire 'scm_i_misc_mutex' and sit there forever because it was
    already taken.
    
    Reported at <https://bugs.gnu.org/29335>.
    
    * libguile/filesys.c (scm_opendir): Allocate storage for a mutex and
    store it as the third word of the SMOB.
    (scm_readdir): Use that mutex instead of 'scm_i_misc_mutex'.  Fixes the
    deadlock upon error.
    (scm_rewindir): Lock the mutex around the 'rewinddir' call.
---
 libguile/filesys.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/libguile/filesys.c b/libguile/filesys.c
index af283dd..d146f50 100644
--- a/libguile/filesys.c
+++ b/libguile/filesys.c
@@ -1727,10 +1727,17 @@ SCM_DEFINE (scm_opendir, "opendir", 1, 0, 0,
 #define FUNC_NAME s_scm_opendir
 {
   DIR *ds;
+  scm_i_pthread_mutex_t *mutex;
+
+  mutex = scm_gc_malloc_pointerless (sizeof *mutex, "dirstream-mutex");
+  scm_i_pthread_mutex_init (mutex, NULL);
+
   STRING_SYSCALL (dirname, c_dirname, ds = opendir (c_dirname));
   if (ds == NULL)
     SCM_SYSERROR;
-  SCM_RETURN_NEWSMOB (scm_tc16_dir | (SCM_DIR_FLAG_OPEN<<16), ds);
+
+  SCM_RETURN_NEWSMOB2 (scm_tc16_dir | (SCM_DIR_FLAG_OPEN << 16),
+                      ds, SCM_PACK_POINTER (mutex));
 }
 #undef FUNC_NAME
 
@@ -1743,14 +1750,17 @@ SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0,
 #define FUNC_NAME s_scm_readdir
 {
   SCM ret;
+  scm_i_pthread_mutex_t *mutex;
   struct dirent_or_dirent64 *rdent;
 
   SCM_VALIDATE_DIR (1, port);
   if (!SCM_DIR_OPEN_P (port))
     SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
 
+  mutex = (scm_i_pthread_mutex_t *) SCM_SMOB_DATA_2 (port);
+
   scm_dynwind_begin (0);
-  scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex);
+  scm_i_dynwind_pthread_mutex_lock (mutex);
 
   errno = 0;
   SCM_SYSCALL (rdent = readdir_or_readdir64 ((DIR *) SCM_SMOB_DATA_1 (port)));
@@ -1761,6 +1771,7 @@ SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0,
          : SCM_EOF_VAL);
 
   scm_dynwind_end ();
+
   return ret;
 }
 #undef FUNC_NAME
@@ -1772,11 +1783,17 @@ SCM_DEFINE (scm_rewinddir, "rewinddir", 1, 0, 0,
            "@code{readdir} will return the first directory entry.")
 #define FUNC_NAME s_scm_rewinddir
 {
+  scm_i_pthread_mutex_t *mutex;
+
   SCM_VALIDATE_DIR (1, port);
   if (!SCM_DIR_OPEN_P (port))
     SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
 
+  mutex = (scm_i_pthread_mutex_t *) SCM_SMOB_DATA_2 (port);
+
+  scm_i_pthread_mutex_lock (mutex);
   rewinddir ((DIR *) SCM_SMOB_DATA_1 (port));
+  scm_i_pthread_mutex_unlock (mutex);
 
   return SCM_UNSPECIFIED;
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]