1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; indent-tabs-mode: nil -*-
3 ;;; --- *NIX-specific error conditions.
6 (in-package :iolib.syscalls
)
8 ;;;-------------------------------------------------------------------------
9 ;;; POSIX Syscall Errors
10 ;;;-------------------------------------------------------------------------
12 (define-condition posix-error
(syscall-error)
15 "POSIX-ERRORs are signalled whenever ERRNO is set by a POSIX call."))
17 ;;; HASH TABLE mapping keywords (such as :EAGAIN) to symbols denoting
18 ;;; subtypes of POSIX-ERROR.
19 (defparameter *posix-error-map
* (make-hash-table :test
#'eq
))
21 (defun get-posix-error-condition (keyword)
22 (gethash keyword
*posix-error-map
*))
24 ;;; Define an error condition for each ERRNO value defined in the
25 ;;; ERRNO-VALUES enum type and populate *POSIX-ERROR-MAP*.
27 ((define-posix-errors (keywords)
29 ,@(loop :for kw
:in keywords
:collect
30 (let ((cond-name (intern (symbol-name kw
)))
31 (code (foreign-enum-value 'errno-values kw
)))
33 (define-condition ,cond-name
(posix-error) ()
34 (:default-initargs
:code
,code
:identifier
,kw
))
35 (setf (gethash ,kw
*posix-error-map
*) ',cond-name
)))))))
37 #.
(foreign-enum-keyword-list 'errno-values
)))
39 ;;; Instantiates a subclass of POSIX-ERROR matching ERR or a plain
40 ;;; POSIX-ERROR if no matching subclass is found. ERR can be either a
41 ;;; keyword or an integer both denoting an ERRNO value.
42 (defun make-posix-error (err)
43 (multiple-value-bind (error-keyword error-code
)
45 (keyword (values err
(foreign-enum-value 'errno-values err
:errorp nil
)))
46 (integer (values (foreign-enum-keyword 'errno-values err
:errorp nil
) err
))
47 (t (bug "Non-valid error-designator: ~A" err
)))
48 (unless (and error-keyword error-code
)
49 (bug "A non-existent ~A syscall error has been signaled: ~A, ~A"
50 'errno-values
(or error-keyword
:unknown
) error-code
))
51 (make-condition (get-posix-error-condition error-keyword
))))
53 (declaim (inline posix-error
))
54 (defun signal-posix-error (&optional
(errno (%sys-errno
)))
55 (error (make-posix-error errno
)))