{
struct lxc_list *iterator;
struct lxc_handler *handler = data;
- int devnull_fd = -1;
+ int devnull_fd = -1, ret;
+ char path[PATH_MAX];
if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
SYSERROR("failed to set sigprocmask");
}
#endif
- if (handler->backgrounded) {
+ ret = sprintf(path, "%s/dev/null", handler->conf->rootfs.mount);
+ if (ret < 0 || ret >= sizeof(path)) {
+ SYSERROR("sprintf'd too many chars");
+ goto out_warn_father;
+ }
+
+ /* In order to checkpoint restore, we need to have everything in the
+ * same mount namespace. However, some containers may not have a
+ * reasonable /dev (in particular, they may not have /dev/null), so we
+ * can't set init's std fds to /dev/null by opening it from inside the
+ * container.
+ *
+ * If that's the case, fall back to using the host's /dev/null. This
+ * means that migration won't work, but at least we won't spew output
+ * where it isn't wanted.
+ */
+ if (handler->backgrounded && !handler->conf->autodev && access(path, F_OK) < 0) {
devnull_fd = open_devnull();
if (devnull_fd < 0)
goto out_warn_father;
+ WARN("using host's /dev/null for container init's std fds, migraiton won't work");
}
/* Setup the container, ip, names, utsname, ... */
close(handler->sigfd);
+ if (devnull_fd < 0) {
+ devnull_fd = open_devnull();
+
+ if (devnull_fd < 0)
+ goto out_warn_father;
+ }
+
if (handler->backgrounded && set_stdfds(devnull_fd))
goto out_warn_father;