}
static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
- const char *lxcpath, const char *hashed_sock_name)
+ const char *lxcpath, const char *hashed_sock_name, int rcv_timeout)
{
__do_close int client_fd = -EBADF;
ssize_t ret = -1;
- client_fd = lxc_cmd_connect(name, lxcpath, hashed_sock_name, "command");
+ client_fd = lxc_cmd_connect(name, lxcpath, hashed_sock_name, "command", rcv_timeout);
if (client_fd < 0)
return -1;
}
/*
- * lxc_cmd: Connect to the specified running container, send it a command
- * request and collect the response
+ * lxc_cmd_timeout: Connect to the specified running container, send it a command
+ * request and collect the response with timeout
*
- * @name : name of container to connect to
- * @cmd : command with initialized request to send
- * @stopped : output indicator if the container was not running
- * @lxcpath : the lxcpath in which the container is running
+ * @name : name of container to connect to
+ * @cmd : command with initialized request to send
+ * @stopped : output indicator if the container was not running
+ * @lxcpath : the lxcpath in which the container is running
+ * @hashed_sock_name : the hashed name of the socket (optional, can be NULL)
+ * @rcv_timeout : SO_RCVTIMEO for LXC client_fd socket
*
* Returns the size of the response message on success, < 0 on failure
*
* the slot with lxc_cmd_fd_cleanup(). The socket fd will be returned in the
* cmd response structure.
*/
-static ssize_t lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, bool *stopped,
- const char *lxcpath, const char *hashed_sock_name)
+static ssize_t lxc_cmd_timeout(const char *name, struct lxc_cmd_rr *cmd, bool *stopped,
+ const char *lxcpath, const char *hashed_sock_name, int rcv_timeout)
{
__do_close int client_fd = -EBADF;
bool stay_connected = false;
*stopped = 0;
- client_fd = lxc_cmd_send(name, cmd, lxcpath, hashed_sock_name);
+ /*
+ * We don't want to change anything for the case when the client
+ * socket fd lifetime is longer than the lxc_cmd_timeout() execution.
+ * So it's better not to set SO_RCVTIMEO for client_fd,
+ * because it'll have an affect on the entire socket lifetime.
+ */
+ if (stay_connected)
+ rcv_timeout = 0;
+
+ client_fd = lxc_cmd_send(name, cmd, lxcpath, hashed_sock_name, rcv_timeout);
if (client_fd < 0) {
if (errno == ECONNREFUSED || errno == EPIPE)
*stopped = 1;
return ret;
}
+static ssize_t lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, bool *stopped,
+ const char *lxcpath, const char *hashed_sock_name)
+{
+ return lxc_cmd_timeout(name, cmd, stopped, lxcpath, hashed_sock_name, 0);
+}
+
int lxc_try_cmd(const char *name, const char *lxcpath)
{
bool stopped = false;
}
int lxc_cmd_connect(const char *name, const char *lxcpath,
- const char *hashed_sock_name, const char *suffix)
+ const char *hashed_sock_name, const char *suffix, int rcv_timeout)
{
- int ret, client_fd;
+ int ret;
+ __do_close int client_fd = -EBADF;
char path[LXC_AUDS_ADDR_LEN] = {0};
ret = lxc_make_abstract_socket_name(path, sizeof(path), name, lxcpath,
if (client_fd < 0)
return -1;
- return client_fd;
+ if (lxc_socket_set_timeout(client_fd, rcv_timeout, 0))
+ return log_trace(-1, "Failed to set socket timeout");
+
+ return move_fd(client_fd);
}
int lxc_add_state_client(int state_client_fd, struct lxc_handler *handler,
WRAP_API(int, lxcapi_seccomp_notify_fd_active)
+static bool do_lxcapi_set_timeout(struct lxc_container *c, int timeout)
+{
+ if (!c)
+ return false;
+
+ if (!(timeout > 0 || timeout == -1))
+ return ret_set_errno(-1, -EINVAL);
+
+ c->rcv_timeout = (timeout == -1) ? 0 : timeout;
+
+ return true;
+}
+
+WRAP_API_1(bool, lxcapi_set_timeout, int)
+
struct lxc_container *lxc_container_new(const char *name, const char *configpath)
{
struct lxc_container *c;
c->umount = lxcapi_umount;
c->seccomp_notify_fd = lxcapi_seccomp_notify_fd;
c->seccomp_notify_fd_active = lxcapi_seccomp_notify_fd_active;
+ c->set_timeout = lxcapi_set_timeout;
return c;