3 #include "unix-socket.h"
4 #include "unix-stream-server.h"
6 #define DEFAULT_LOCK_TIMEOUT (100)
9 * Try to connect to a unix domain socket at `path` (if it exists) and
10 * see if there is a server listening.
12 * We don't know if the socket exists, whether a server died and
13 * failed to cleanup, or whether we have a live server listening, so
16 * We immediately hangup without sending/receiving any data because we
17 * don't know anything about the protocol spoken and don't want to
18 * block while writing/reading data. It is sufficient to just know
19 * that someone is listening.
21 static int is_another_server_alive(const char *path
,
22 const struct unix_stream_listen_opts
*opts
)
24 int fd
= unix_stream_connect(path
, opts
->disallow_chdir
);
33 int unix_ss_create(const char *path
,
34 const struct unix_stream_listen_opts
*opts
,
36 struct unix_ss_socket
**new_server_socket
)
38 struct lock_file lock
= LOCK_INIT
;
40 struct unix_ss_socket
*server_socket
;
42 *new_server_socket
= NULL
;
45 timeout_ms
= DEFAULT_LOCK_TIMEOUT
;
48 * Create a lock at "<path>.lock" if we can.
50 if (hold_lock_file_for_update_timeout(&lock
, path
, 0, timeout_ms
) < 0)
54 * If another server is listening on "<path>" give up. We do not
55 * want to create a socket and steal future connections from them.
57 if (is_another_server_alive(path
, opts
)) {
58 rollback_lock_file(&lock
);
64 * Create and bind to a Unix domain socket at "<path>".
66 fd_socket
= unix_stream_listen(path
, opts
);
68 int saved_errno
= errno
;
69 rollback_lock_file(&lock
);
74 server_socket
= xcalloc(1, sizeof(*server_socket
));
75 server_socket
->path_socket
= strdup(path
);
76 server_socket
->fd_socket
= fd_socket
;
77 lstat(path
, &server_socket
->st_socket
);
79 *new_server_socket
= server_socket
;
82 * Always rollback (just delete) "<path>.lock" because we already created
83 * "<path>" as a socket and do not want to commit_lock to do the atomic
86 rollback_lock_file(&lock
);
91 void unix_ss_free(struct unix_ss_socket
*server_socket
)
96 if (server_socket
->fd_socket
>= 0) {
97 if (!unix_ss_was_stolen(server_socket
))
98 unlink(server_socket
->path_socket
);
99 close(server_socket
->fd_socket
);
102 free(server_socket
->path_socket
);
106 int unix_ss_was_stolen(struct unix_ss_socket
*server_socket
)
113 if (lstat(server_socket
->path_socket
, &st_now
) == -1)
116 if (st_now
.st_ino
!= server_socket
->st_socket
.st_ino
)
118 if (st_now
.st_dev
!= server_socket
->st_socket
.st_dev
)
121 if (!S_ISSOCK(st_now
.st_mode
))