Commit54dea422Recorded24 Mar 2026Repositorysigil-socket
Add unix-listen for Unix domain socket server support
Message
Adds native unix-listen function (C + Scheme wrapper) to sigil-socket, enabling creation of listening Unix domain sockets. Removes stale socket files before binding. Reuses tcp-accept for connections. Includes tests.
Also adds test output grep tip to CLAUDE.md.
Changed
src/sigil/socket.sgl | 14 ++++++++++++++
test/test-socket.sgl | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 66 insertions(+), 1 deletion(-)Diff
src/sigil/socket.sglmodified
@@ -48,6 +48,7 @@
48
49
;; Unix domain sockets 50
unix-connect+51
unix-listen 52
53
;; UDP operations 54
udp-socket@@ -282,6 +283,19 @@
283
(define-native (unix-connect path) 284
(: string? -> (maybe socket?))) 285
+286
;;; Create a listening Unix domain socket.+287
;;;+288
;;; Binds to the specified path and begins listening for connections.+289
;;; Removes any stale socket file at the path before binding.+290
;;; Use `tcp-accept` to accept incoming connections.+291
;;; Not available on Windows.+292
;;;+293
;;; ```scheme+294
;;; (unix-listen "/tmp/my-server.sock") ; => #<socket>+295
;;; ```+296
(define-native (unix-listen path)+297
(: string? -> (maybe socket?)))+298
299
;; ========== Higher-Level Utilities ========== 300
301
;;; Connect to a TCP server, call proc with the socket, then close it.test/test-socket.sglmodified
@@ -1,5 +1,6 @@
1
(import (sigil test)−2
(sigil socket))+2
(sigil socket)+3
(sigil fs)) 4
5
;; ============================================================ 6
;; TCP echo@@ -273,6 +274,56 @@
274
(for-each socket-close peers))))) 275
(socket-close server)))) 276
+277
;; ============================================================+278
;; Unix domain sockets+279
;; ============================================================+280
+281
(test-group "Unix domain sockets"+282
(test "unix-listen creates a socket"+283
(let ((server (unix-listen "/tmp/sigil-test-unix.sock")))+284
(assert-true (socket? server))+285
(socket-close server)+286
(delete-file "/tmp/sigil-test-unix.sock")))+287
+288
(test "unix-connect to unix-listen socket"+289
(let ((server (unix-listen "/tmp/sigil-test-unix2.sock")))+290
(let ((client (unix-connect "/tmp/sigil-test-unix2.sock")))+291
(assert-true (socket? client))+292
(socket-close client))+293
(socket-close server)+294
(delete-file "/tmp/sigil-test-unix2.sock")))+295
+296
(test "unix echo via accept"+297
(let ((server (unix-listen "/tmp/sigil-test-unix3.sock")))+298
(let* ((client (unix-connect "/tmp/sigil-test-unix3.sock"))+299
(peer (tcp-accept server)))+300
(assert-true (socket? peer))+301
(socket-write-line client "hello unix")+302
(let ((received (socket-read-line peer)))+303
(assert-equal "hello unix" received))+304
(socket-write-line peer "reply")+305
(let ((reply (socket-read-line client)))+306
(assert-equal "reply" reply))+307
(socket-close peer)+308
(socket-close client))+309
(socket-close server)+310
(delete-file "/tmp/sigil-test-unix3.sock")))+311
+312
(test "unix-listen removes stale socket file"+313
(let ((path "/tmp/sigil-test-unix4.sock"))+314
;; Create a socket, close it (leaves stale file)+315
(let ((s1 (unix-listen path)))+316
(socket-close s1))+317
;; Should succeed even though file exists+318
(let ((s2 (unix-listen path)))+319
(assert-true (socket? s2))+320
(socket-close s2)+321
(delete-file path))))+322
+323
(test "unix-connect to nonexistent path returns #f"+324
(let ((result (unix-connect "/tmp/sigil-test-nonexistent.sock")))+325
(assert-false result))))+326
327
(test-group "error handling" 328
(test "tcp-connect to closed port returns #f" 329
;; Bind a server to get a port, close it, then try to connect