~ chicken-core (chicken-5) 251e3ce628dcfa5d8a6bfa5b128f4cc4fb4c1b8b


commit 251e3ce628dcfa5d8a6bfa5b128f4cc4fb4c1b8b
Author:     Mario Domenech Goulart <mario@parenteses.org>
AuthorDate: Sat Jan 6 19:43:04 2024 +0100
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Sun Jan 7 12:09:40 2024 +0100

    Add errno property to condition objects
    
    From c9f4b699a907f1b619fdb11e0051cc697decf2cf Mon Sep 17 00:00:00 2001
    From: Mario Domenech Goulart <mario@parenteses.org>
    Date: Sat, 6 Jan 2024 13:12:40 +0100
    Subject: [PATCH] Add errno property to condition objects
    
    This change introduces two new internal procedures that inject errno
    into condition objects produced by procedures whose underlying C calls
    update it:
    
    * ##sys#error/errno
    * ##sys#signal-hook/errno
    
    Signed-off-by: felix <felix@call-with-current-continuation.org>

diff --git a/NEWS b/NEWS
index ffb42e1e..46c5d423 100644
--- a/NEWS
+++ b/NEWS
@@ -33,6 +33,8 @@
     export.
   - The values of the TMPDIR, TMP and TEMP environment variables are no
     longer memoized (fixes #1830).
+  - Condition objects produced by procedures that change errno now have
+    an `errno' property.
 
 - Tools
   - The -R option for csi and csc now accepts list-notation like
diff --git a/file.scm b/file.scm
index 78d68a41..f8f45bd9 100644
--- a/file.scm
+++ b/file.scm
@@ -116,7 +116,8 @@ EOF
 	[string-append string-append] )
     (lambda (type loc msg . args)
       (let ([rn (##sys#update-errno)])
-	(apply ##sys#signal-hook type loc (string-append msg " - " (strerror rn)) args) ) ) ) )
+        (apply ##sys#signal-hook/errno
+               type rn loc (string-append msg " - " (strerror rn)) args)))))
 
 
 ;;; Existence checks:
@@ -225,11 +226,10 @@ EOF
 (define (delete-file filename)
   (##sys#check-string filename 'delete-file)
   (unless (eq? 0 (##core#inline "C_remove" (##sys#make-c-string filename 'delete-file)))
-    (##sys#update-errno)
-    (##sys#signal-hook
-     #:file-error 'delete-file
-     (##sys#string-append "cannot delete file - " strerror) filename))
-  filename)
+    (##sys#signal-hook/errno
+     #:file-error (##sys#update-errno) 'delete-file
+     (##sys#string-append "cannot delete file - " strerror) filename)
+    filename))
 
 (define (delete-file* file)
   (and (file-exists? file) (delete-file file)))
@@ -243,9 +243,8 @@ EOF
 		  "C_rename"
 		  (##sys#make-c-string oldfile 'rename-file)
 		  (##sys#make-c-string newfile 'rename-file)))
-    (##sys#update-errno)
-    (##sys#signal-hook
-     #:file-error 'rename-file
+    (##sys#signal-hook/errno
+     #:file-error (##sys#update-errno) 'rename-file
      (##sys#string-append "cannot rename file - " strerror) oldfile newfile))
   newfile)
 
diff --git a/library.scm b/library.scm
index 7341bb66..3ec87a74 100644
--- a/library.scm
+++ b/library.scm
@@ -40,7 +40,7 @@
 	+maximum-allowed-exponent+ mantexp->dbl ldexp round-quotient
 	##sys#string->compnum ##sys#internal-gcd)
   (not inline chicken.base#sleep-hook ##sys#change-directory-hook
-       ##sys#user-read-hook ##sys#error-hook ##sys#signal-hook
+       ##sys#user-read-hook ##sys#error-hook ##sys#signal-hook ##sys#signal-hook/errno
        ##sys#default-read-info-hook ##sys#infix-list-hook
        ##sys#sharp-number-hook ##sys#user-print-hook
        ##sys#user-interrupt-hook ##sys#windows-platform
@@ -1049,6 +1049,11 @@ EOF
 (define ##sys#warn warning)
 (define ##sys#notice notice)
 
+(define (##sys#error/errno err . args)
+  (if (pair? args)
+      (apply ##sys#signal-hook/errno #:error err #f args)
+      (##sys#signal-hook/errno #:error err #f)))
+
 (define-foreign-variable strerror c-string "strerror(errno)")
 
 (define ##sys#gc (##core#primitive "C_gc"))
@@ -3225,24 +3230,26 @@ EOF
 	      (let ((c (##core#inline "C_read_char" p)))
 		(cond
 		 ((eq? -1 c)
-		  (if (eq? (##sys#update-errno) (foreign-value "EINTR" int))
-		      (##sys#dispatch-interrupt loop)
-		      (##sys#signal-hook
-		       #:file-error 'read-char
-		       (##sys#string-append "cannot read from port - " strerror)
-		       p)))
+                  (let ((err (##sys#update-errno)))
+                    (if (eq? err (foreign-value "EINTR" int))
+                        (##sys#dispatch-interrupt loop)
+                        (##sys#signal-hook/errno
+                         #:file-error err 'read-char
+                         (##sys#string-append "cannot read from port - " strerror)
+                         p))))
 		 (else c)))))
 	  (lambda (p)			; peek-char
 	    (let loop ()
 	      (let ((c (##core#inline "C_peek_char" p)))
 		(cond
 		 ((eq? -1 c)
-		  (if (eq? (##sys#update-errno) (foreign-value "EINTR" int))
-		      (##sys#dispatch-interrupt loop)
-		      (##sys#signal-hook
-		       #:file-error 'peek-char
-		       (##sys#string-append "cannot read from port - " strerror)
-		       p)))
+                  (let ((err (##sys#update-errno)))
+                    (if (eq? err (foreign-value "EINTR" int))
+                        (##sys#dispatch-interrupt loop)
+                        (##sys#signal-hook/errno
+                         #:file-error err 'peek-char
+                         (##sys#string-append "cannot read from port - " strerror)
+                         p))))
 		 (else c)))))
 	  (lambda (p c)			; write-char
 	    (##core#inline "C_display_char" p c) )
@@ -3261,14 +3268,15 @@ EOF
 		(cond ((eof-object? len) ; EOF returns 0 bytes read
 		       act)
 		      ((fx< len 0)
-		       (if (eq? (##sys#update-errno) (foreign-value "EINTR" int))
-			   (##sys#dispatch-interrupt
-			    (lambda ()
-			      (loop (fx- rem len) (fx+ act len) (fx+ start len))))
-			   (##sys#signal-hook
-			    #:file-error 'read-string!
-			    (##sys#string-append "cannot read from port - " strerror)
-			    p n dest start)))
+                       (let ((err (##sys#update-errno)))
+                         (if (eq? err (foreign-value "EINTR" int))
+                             (##sys#dispatch-interrupt
+                              (lambda ()
+                                (loop (fx- rem len) (fx+ act len) (fx+ start len))))
+                             (##sys#signal-hook/errno
+                              #:file-error err 'read-string!
+                              (##sys#string-append "cannot read from port - " strerror)
+                              p n dest start))))
 		      ((fx< len rem)
 		       (loop (fx- rem len) (fx+ act len) (fx+ start len)))
 		      (else
@@ -3295,18 +3303,19 @@ EOF
 				   (##sys#string-append result buffer)
 				   #t)) ]
 			((fx< n 0)
-			 (if (eq? (##sys#update-errno) (foreign-value "EINTR" int))
-			     (let ((n (fx- (fxneg n) 1)))
-			       (##sys#dispatch-interrupt
-				(lambda ()
-				  (loop len limit buffer
-					(##sys#string-append
-					 result (##sys#substring buffer 0 n))
-					#t))))
-			     (##sys#signal-hook
-			      #:file-error 'read-line
-			      (##sys#string-append "cannot read from port - " strerror)
-			      p rlimit)))
+                         (let ((err (##sys#update-errno)))
+                           (if (eq? err (foreign-value "EINTR" int))
+                               (let ((n (fx- (fxneg n) 1)))
+                                 (##sys#dispatch-interrupt
+                                  (lambda ()
+                                    (loop len limit buffer
+                                          (##sys#string-append
+                                           result (##sys#substring buffer 0 n))
+                                          #t))))
+                               (##sys#signal-hook/errno
+                                #:file-error err 'read-line
+                                (##sys#string-append "cannot read from port - " strerror)
+                                p rlimit))))
 			[f (##sys#setislot p 4 (fx+ (##sys#slot p 4) 1))
 			   (##sys#string-append result (##sys#substring buffer 0 n))]
 			[else
@@ -3400,8 +3409,9 @@ EOF
             [else (##sys#error loc "invalid file option" o)] ) ) )
       (let ((port (##sys#make-port (if inp 1 2) ##sys#stream-port-class name 'stream)))
         (unless (##sys#open-file-port port name (##sys#string-append fmode bmode))
-          (##sys#update-errno)
-          (##sys#signal-hook #:file-error loc (##sys#string-append "cannot open file - " strerror) name) )
+          (##sys#signal-hook/errno #:file-error (##sys#update-errno) loc
+                                   (##sys#string-append "cannot open file - " strerror)
+                                   name))
         port) ) )
 
   (define (close port inp loc)
@@ -5105,7 +5115,7 @@ EOF
 (import scheme chicken.base chicken.fixnum chicken.foreign)
 (import chicken.internal.syntax)
 
-(define (##sys#signal-hook mode msg . args)
+(define (##sys#signal-hook/errno mode errno msg . args)
   (##core#inline "C_dbg_hook" #f)
   (##core#inline "signal_debug_event" mode msg args)
   (case mode
@@ -5132,7 +5142,7 @@ EOF
 	   (##sys#write-char-0 #\newline ##sys#standard-error))))
       args)
      (##sys#flush-output ##sys#standard-error)]
-    [else
+    (else
      (when (and (symbol? msg) (null? args))
        (set! msg (symbol->string msg)))
      (let* ([hasloc (and (or (not msg) (symbol? msg)) (pair? args))]
@@ -5158,10 +5168,19 @@ EOF
 	   [(#:domain-error)		'(exn domain)]
 	   ((#:memory-error)            '(exn memory))
 	   [else			'(exn)] )
-	 (list '(exn . message) msg
-	       '(exn . arguments) args
-	       '(exn . call-chain) (get-call-chain)
-	       '(exn . location) loc) ) ) ) ] ) )
+         (let ((props
+                (list '(exn . message) msg
+                      '(exn . arguments) args
+                      '(exn . call-chain) (get-call-chain)
+                      '(exn . location) loc)))
+           (if errno
+               (cons '(exn . errno) (cons errno props))
+               props))))))))
+
+(define (##sys#signal-hook mode msg . args)
+  (if (pair? args)
+      (apply ##sys#signal-hook/errno mode #f msg args)
+      (##sys#signal-hook/errno mode #f msg)))
 
 (define (abort x)
   (##sys#current-exception-handler x)
@@ -6034,8 +6053,7 @@ static C_word C_fcall C_setenv(C_word x, C_word y) {
   (##sys#check-string name 'change-directory)
   (let ((sname (##sys#make-c-string name 'change-directory)))
     (unless (fx= (##core#inline "C_chdir" sname) 0)
-      (##sys#update-errno)
-      (##sys#signal-hook #:file-error 'change-directory
+      (##sys#signal-hook/errno #:file-error (##sys#update-errno) 'change-directory
        (string-append "cannot change current directory - " strerror) name))
     name))
 
@@ -6052,9 +6070,10 @@ static C_word C_fcall C_setenv(C_word x, C_word y) {
 	(##sys#update-errno))
       (if len
 	  (##sys#substring buffer 0 len)
-	  (##sys#signal-hook
-	   #:file-error
-	   'current-directory "cannot retrieve current directory"))))
+          (##sys#signal-hook/errno
+           #:file-error
+           (##sys#errno)
+           'current-directory "cannot retrieve current directory"))))
    (lambda (dir)
      (##sys#change-directory-hook dir))
    "(chicken.process-context#current-directory)"))
diff --git a/manual/Module (chicken condition) b/manual/Module (chicken condition)
index 522b51f5..d057f427 100644
--- a/manual/Module (chicken condition)	
+++ b/manual/Module (chicken condition)	
@@ -102,6 +102,10 @@ possible. If the unwinding and handling of the signal raises one of
 these signals once again, the process will abort with an error
 message.
 
+* New in CHICKEN 5.4.0: condition objects produced by procedures that
+change errno have an {{errno}} property.  To access it, use
+{{(get-condition-property <the-condition-object> 'exn 'errno)}}.
+
 === Additional API
 
 ==== condition-case
diff --git a/manual/Module (chicken file posix) b/manual/Module (chicken file posix)
index 1140ef19..14e95132 100644
--- a/manual/Module (chicken file posix)	
+++ b/manual/Module (chicken file posix)	
@@ -13,6 +13,11 @@ systems like Windows. See below for Windows specific notes.
 All errors related to failing file-operations will signal a condition
 of kind {{(exn i/o file)}}.
 
+* New in CHICKEN 5.4.0: Errors caused by underlying C calls that
+  change errno will produce a condition object with an {{errno}}
+  property, which can be accessed with
+  {{(get-condition-property <the-condition-object> 'exn 'errno)}}.
+
 === Constants
 
 ==== File-control Commands
diff --git a/manual/Module (chicken file) b/manual/Module (chicken file)
index 4dd96d08..e2804508 100644
--- a/manual/Module (chicken file)	
+++ b/manual/Module (chicken file)	
@@ -10,6 +10,11 @@ directories.  For more specific operations, see also
 All errors related to failing file-operations will signal a condition
 of kind {{(exn i/o file)}}.
 
+* New in CHICKEN 5.4.0: Errors caused by underlying C calls that
+  change errno will produce a condition object with an {{errno}}
+  property, which can be accessed with
+  {{(get-condition-property <the-condition-object> 'exn 'errno)}}.
+
 === Basic file operations
 
 ==== create-directory
diff --git a/manual/Module (chicken port) b/manual/Module (chicken port)
index 996b87ff..ba8c268f 100644
--- a/manual/Module (chicken port)	
+++ b/manual/Module (chicken port)	
@@ -5,6 +5,14 @@
 
 This module contains various extended port definitions.
 
+All errors related to failing port operations will signal a condition
+of kind {{exn}}.
+
+* New in CHICKEN 5.4.0: Errors caused by underlying C calls that
+  change errno will produce a condition object with an {{errno}}
+  property, which can be accessed with
+  {{(get-condition-property <the-condition-object> 'exn 'errno)}}.
+
 === Port attributes
 
 ==== port-name
diff --git a/manual/Module (chicken process) b/manual/Module (chicken process)
index 26f225c3..3105798a 100644
--- a/manual/Module (chicken process)	
+++ b/manual/Module (chicken process)	
@@ -5,6 +5,10 @@
 
 This module offers procedures for interacting with subprocesses.
 
+* New in CHICKEN 5.4.0: Errors caused by underlying C calls that
+  change errno will produce a condition object with an {{errno}}
+  property, which can be accessed with
+  {{(get-condition-property <the-condition-object> 'exn 'errno)}}.
 
 === Processes
 
diff --git a/manual/Module (chicken process-context posix) b/manual/Module (chicken process-context posix)
index 0b4e9426..192ba588 100644
--- a/manual/Module (chicken process-context posix)	
+++ b/manual/Module (chicken process-context posix)	
@@ -6,6 +6,11 @@
 This module provides access to POSIX-specific procedures which deal
 with the current process context.
 
+* New in CHICKEN 5.4.0: Errors caused by underlying C calls that
+  change errno will produce a condition object with an {{errno}}
+  property, which can be accessed with
+  {{(get-condition-property <the-condition-object> 'exn 'errno)}}.
+
 === Process filesystem context
 
 ==== change-directory*
diff --git a/manual/Module (chicken process-context) b/manual/Module (chicken process-context)
index 87165187..b30f4d08 100644
--- a/manual/Module (chicken process-context)	
+++ b/manual/Module (chicken process-context)	
@@ -5,6 +5,11 @@
 
 This module provides access to the current process context.
 
+* New in CHICKEN 5.4.0: Errors caused by underlying C calls that
+  change errno will produce a condition object with an {{errno}}
+  property, which can be accessed with
+  {{(get-condition-property <the-condition-object> 'exn 'errno)}}.
+
 === Information about the program's invocation
 
 ==== argc+argv
diff --git a/port.scm b/port.scm
index 8826d13a..38dbec85 100644
--- a/port.scm
+++ b/port.scm
@@ -411,7 +411,8 @@ char *ttyname(int fd) {
 	(string-append string-append))
     (lambda (type loc msg . args)
       (let ((rn (##sys#update-errno)))
-	(apply ##sys#signal-hook type loc (string-append msg " - " (strerror rn)) args)))))
+        (apply ##sys#signal-hook/errno
+               type rn loc (string-append msg " - " (strerror rn)) args)))))
 
 ;; Terminal ports
 (define (terminal-port? port)
diff --git a/posix-common.scm b/posix-common.scm
index 6f7028c3..96e4da10 100644
--- a/posix-common.scm
+++ b/posix-common.scm
@@ -189,7 +189,8 @@ EOF
 	[string-append string-append] )
     (lambda (type loc msg . args)
       (let ([rn (##sys#update-errno)])
-	(apply ##sys#signal-hook type loc (string-append msg " - " (strerror rn)) args) ) ) ) )
+        (apply ##sys#signal-hook/errno
+               type rn loc (string-append msg " - " (strerror rn)) args)))))
 
 (define ##sys#posix-error posix-error)
 
diff --git a/posix.scm b/posix.scm
index a082f054..78e54065 100644
--- a/posix.scm
+++ b/posix.scm
@@ -199,8 +199,8 @@
   (##sys#check-string cmd 'system)
   (let ((r (##core#inline "C_execute_shell_command" cmd)))
     (cond ((fx< r 0)
-	   (##sys#update-errno)
-	   (##sys#signal-hook #:process-error 'system "`system' invocation failed" cmd))
+           (##sys#signal-hook/errno
+            #:process-error (##sys#update-errno) 'system "`system' invocation failed" cmd))
 	  (else r))))
 
 ;;; Like `system', but bombs on nonzero return code:
diff --git a/posixunix.scm b/posixunix.scm
index 213f7492..bad9b4c0 100644
--- a/posixunix.scm
+++ b/posixunix.scm
@@ -604,8 +604,8 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
    (lambda (id)
      (##sys#check-fixnum id 'current-user-id)
      (when (fx< (##core#inline "C_setuid" id) 0)
-       (##sys#update-errno)
-       (##sys#error 'current-user-id!-setter "cannot set user ID" id) ) )
+       (##sys#error/errno (##sys#update-errno)
+                          'current-user-id!-setter "cannot set user ID" id)))
    "(chicken.process-context.posix#current-user-id)"))
 
 (set! chicken.process-context.posix#current-effective-user-id
@@ -614,9 +614,9 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
    (lambda (id)
      (##sys#check-fixnum id 'current-effective-user-id)
      (when (fx< (##core#inline "C_seteuid" id) 0)
-       (##sys#update-errno)
-       (##sys#error
-	'effective-user-id!-setter "cannot set effective user ID" id) ) )
+       (##sys#error/errno (##sys#update-errno)
+                          'effective-user-id!-setter
+                          "cannot set effective user ID" id)))
    "(chicken.process-context.posix#current-effective-user-id)"))
 
 (set! chicken.process-context.posix#current-group-id
@@ -625,8 +625,8 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
    (lambda (id)
      (##sys#check-fixnum id 'current-group-id)
      (when (fx< (##core#inline "C_setgid" id) 0)
-       (##sys#update-errno)
-       (##sys#error 'current-group-id!-setter "cannot set group ID" id) ) )
+       (##sys#error/errno (##sys#update-errno)
+                          'current-group-id!-setter "cannot set group ID" id)))
    "(chicken.process-context.posix#current-group-id)") )
 
 (set! chicken.process-context.posix#current-effective-group-id
@@ -635,9 +635,9 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
    (lambda (id)
      (##sys#check-fixnum id 'current-effective-group-id)
      (when (fx< (##core#inline "C_setegid" id) 0)
-       (##sys#update-errno)
-       (##sys#error
-	'effective-group-id!-setter "cannot set effective group ID" id) ) )
+       (##sys#error/errno (##sys#update-errno)
+                          'effective-group-id!-setter
+                          "cannot set effective group ID" id)))
    "(chicken.process-context.posix#current-effective-group-id)") )
 
 (define-foreign-variable _user-name nonnull-c-string "C_user->pw_name")
@@ -697,8 +697,8 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
   (lambda ()
    (let ([a (##core#inline "C_setsid" #f)])
      (when (fx< a 0)
-	   (##sys#update-errno)
-	   (##sys#error 'create-session "cannot create session") )
+       (##sys#error/errno (##sys#update-errno)
+                          'create-session "cannot create session"))
      a)) )
 
 (set! chicken.process-context.posix#process-group-id
@@ -707,15 +707,16 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
      (##sys#check-fixnum pid 'process-group-id)
      (let ([a (##core#inline "C_getpgid" pid)])
        (when (fx< a 0)
-         (##sys#update-errno)
-         (##sys#error 'process-group-id "cannot retrieve process group ID" pid) )
+         (##sys#error/errno (##sys#update-errno)
+                            'process-group-id
+                            "cannot retrieve process group ID" pid))
        a))
    (lambda (pid pgid)
      (##sys#check-fixnum pid 'process-group)
      (##sys#check-fixnum pgid 'process-group)
      (when (fx< (##core#inline "C_setpgid" pid pgid) 0)
-       (##sys#update-errno)
-       (##sys#error 'process-group "cannot set process group ID" pid pgid) ) )
+       (##sys#error/errno (##sys#update-errno)
+                          'process-group "cannot set process group ID" pid pgid)))
    "(chicken.process-context.posix#process-group-id pid)"))
 
 
diff --git a/posixwin.scm b/posixwin.scm
index d3e607d8..cadba1b3 100644
--- a/posixwin.scm
+++ b/posixwin.scm
@@ -525,8 +525,8 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
 	(##sys#check-fixnum mode 'file-open)
 	(let ([fd (##core#inline "C_open" (##sys#make-c-string filename 'file-open) flags mode)])
 	  (when (eq? -1 fd)
-	    (##sys#update-errno)
-	    (##sys#signal-hook #:file-error 'file-open "cannot open file" filename flags mode) )
+            (##sys#signal-hook/errno
+             #:file-error (##sys#update-errno) 'file-open "cannot open file" filename flags mode))
 	  fd) ) ) ) )
 
 (set! chicken.file.posix#file-close
@@ -548,8 +548,8 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
 	(##sys#signal-hook #:type-error 'file-read "bad argument type - not a string or blob" buf) )
       (let ([n (##core#inline "C_read" fd buf size)])
 	(when (eq? -1 n)
-	  (##sys#update-errno)
-	  (##sys#signal-hook #:file-error 'file-read "cannot read from file" fd size) )
+          (##sys#signal-hook/errno
+           #:file-error (##sys#update-errno) 'file-read "cannot read from file" fd size))
 	(list buf n) ) ) ) )
 
 (set! chicken.file.posix#file-write
@@ -561,8 +561,8 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
       (##sys#check-fixnum size 'file-write)
       (let ([n (##core#inline "C_write" fd buffer size)])
 	(when (eq? -1 n)
-	  (##sys#update-errno)
-	  (##sys#signal-hook #:file-error 'file-write "cannot write to file" fd size) )
+          (##sys#signal-hook/errno
+           #:file-error (##sys#update-errno) 'file-write "cannot write to file" fd size))
 	n) ) ) )
 
 (set! chicken.file.posix#file-mkstemp
@@ -612,8 +612,8 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
   (lambda (#!optional (mode (fxior chicken.file.posix#open/binary
                                    chicken.file.posix#open/noinherit)))
     (when (fx< (##core#inline "C_pipe" #f mode) 0)
-      (##sys#update-errno)
-      (##sys#signal-hook #:file-error 'create-pipe "cannot create pipe") )
+      (##sys#signal-hook/errno
+       #:file-error (##sys#update-errno) 'create-pipe "cannot create pipe"))
     (values _pipefd0 _pipefd1) ) )
 
 ;;; Signal processing:
@@ -676,8 +676,8 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
 		    (##sys#check-fixnum n 'duplicate-fileno)
 		    (##core#inline "C_dup2" old n) ) ) ] )
       (when (fx< fd 0)
-	(##sys#update-errno)
-	(##sys#signal-hook #:file-error 'duplicate-fileno "cannot duplicate file descriptor" old) )
+        (##sys#signal-hook/errno
+         #:file-error (##sys#update-errno) 'duplicate-fileno "cannot duplicate file descriptor" old))
       fd) ) )
 
 
@@ -754,9 +754,8 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
   (or (get-environment-variable "COMSPEC")
       (if (##core#inline "C_get_shlcmd")
 	  _shlcmd
-	  (begin
-	    (##sys#update-errno)
-	    (##sys#error loc "cannot retrieve system directory") ) ) ) )
+          (##sys#error/errno
+           (##sys#update-errno) loc "cannot retrieve system directory"))))
 
 (define (shell-command-arguments cmdlin)
   (list "/c" cmdlin) )
@@ -820,9 +819,8 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
 	       handle
 	       (and stderrf (chicken.file.posix#open-input-file*
 			     stderr_fd)))
-	      (begin
-		(##sys#update-errno)
-		(##sys#signal-hook #:process-error loc "cannot execute process" cmdlin))) ) ) ) ) ) )
+              (##sys#signal-hook/errno
+               #:process-error (##sys#update-errno) loc "cannot execute process" cmdlin))))))))
 
 ;; TODO: See if this can be moved to posix-common
 (let ((%process
@@ -867,9 +865,8 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime)
   (lambda ()
     (if (##core#inline "C_get_user_name")
         _username
-        (begin
-          (##sys#update-errno)
-          (##sys#error 'current-user-name "cannot retrieve current user-name") ) ) ) )
+        (##sys#error/errno
+         (##sys#update-errno) 'current-user-name "cannot retrieve current user-name"))))
 
 
 ;;; unimplemented stuff:
diff --git a/tests/condition-tests.scm b/tests/condition-tests.scm
index 207b6231..3253fe81 100644
--- a/tests/condition-tests.scm
+++ b/tests/condition-tests.scm
@@ -32,3 +32,20 @@
 (assert (equal? (condition->list condition3)
 		'((exn message "foo" arguments ("bar") location test)
 		  (sam age 23 partner "max"))))
+
+;; testing errno in condition objects
+
+(import (chicken errno)
+        (chicken file)
+        (chicken process-context))
+
+(let ((nonexistent-path "this/path/does/not/exist/,hopefully"))
+  (assert (not (file-exists? nonexistent-path)))
+
+  (handle-exceptions exn
+    (assert (= (get-condition-property exn 'exn 'errno) errno/noent))
+    (delete-file nonexistent-path))
+
+  (handle-exceptions exn
+    (assert (= (get-condition-property exn 'exn 'errno) errno/noent))
+    (change-directory nonexistent-path)))
Trap