From c159fc4197ad06d603ba404add501ac02d76c64f Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 27 Jun 2014 09:04:51 +0200 Subject: [PATCH] Bugfix: create the directory for storing the restart state (Thanks hjem) fixes #1303 --- include/ipc.h | 6 +++ src/commands.c | 5 +-- src/ipc.c | 2 +- src/util.c | 9 ++++ testcases/t/229-cleanup-tmpdir.t | 76 ++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 5 deletions(-) diff --git a/include/ipc.h b/include/ipc.h index 418b040f..5fa4334a 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -50,6 +50,12 @@ typedef void(*handler_t)(int, uint8_t*, int, uint32_t, uint32_t); int size, uint32_t message_size, \ uint32_t message_type) +/** + * Emulates mkdir -p (creates any missing folders) + * + */ +bool mkdirp(const char *path); + /** * Handler for activity on the listening socket, meaning that a new client * has just connected and we should accept() him. Sets up the event handler diff --git a/src/commands.c b/src/commands.c index 03bb10a6..bb44ffde 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1685,13 +1685,10 @@ void cmd_reload(I3_CMD) { void cmd_restart(I3_CMD) { LOG("restarting i3\n"); ipc_shutdown(); + unlink(config.ipc_socket_path); /* We need to call this manually since atexit handlers don’t get called * when exec()ing */ purge_zerobyte_logfile(); - /* The unlink call is intentionally after the purge_zerobyte_logfile() so - * that the latter does not remove the directory yet. We need to store the - * restart layout state in there. */ - unlink(config.ipc_socket_path); i3_restart(false); // XXX: default reply for now, make this a better reply diff --git a/src/ipc.c b/src/ipc.c index 0f3dcd82..66c28bdc 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -41,7 +41,7 @@ static void set_nonblock(int sockfd) { * Emulates mkdir -p (creates any missing folders) * */ -static bool mkdirp(const char *path) { +bool mkdirp(const char *path) { if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0) return true; if (errno != ENOENT) { diff --git a/src/util.c b/src/util.c index c40f6581..b382a586 100644 --- a/src/util.c +++ b/src/util.c @@ -249,6 +249,15 @@ char *store_restart_layout(void) { filename = resolve_tilde(config.restart_state_path); } + /* create the directory, it could have been cleaned up before restarting or + * may not exist at all in case it was user-specified. */ + char *filenamecopy = sstrdup(filename); + char *base = dirname(filenamecopy); + DLOG("Creating \"%s\" for storing the restart layout\n", base); + if (!mkdirp(base)) + ELOG("Could not create \"%s\" for storing the restart layout, layout will be lost.\n", base); + free(filenamecopy); + int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fd == -1) { perror("open()"); diff --git a/testcases/t/229-cleanup-tmpdir.t b/testcases/t/229-cleanup-tmpdir.t index eff39b08..cec9bc4d 100644 --- a/testcases/t/229-cleanup-tmpdir.t +++ b/testcases/t/229-cleanup-tmpdir.t @@ -19,6 +19,8 @@ # Bug still in: 4.7.2-186-g617afc6 use i3test i3_autostart => 0; use File::Basename; +use File::Temp qw(tempfile tempdir); +use X11::XCB qw(:all); my $config = < 1); +$config = < 1, dont_create_temp_dir => 1); +$socketpath = get_socket_path(0); + +sub get_config_path { + my $atom = $x->atom(name => 'I3_CONFIG_PATH'); + my $cookie = $x->get_property(0, $x->get_root_window(), $atom->id, GET_PROPERTY_TYPE_ANY, 0, 256); + my $reply = $x->get_property_reply($cookie->{sequence}); + return $reply->{value}; +} + +my ($outfh2, $outname2) = tempfile('/tmp/i3-socket.XXXXXX', UNLINK => 1); +my $config_path = get_config_path(); +open(my $configfh, '>', $config_path); +say $configfh <; +for my $fn (@errorlogfiles) { + open(my $fh, '>', $fn); + close($fh); +} + +my $tmp = fresh_workspace; +my $win = open_window; +cmd 'border none'; +my ($nodes, $focus) = get_ws_content($tmp); +is($nodes->[0]->{border}, 'none', 'border is none'); + +cmd 'restart'; + +# The socket path will be different, and we use that for checking whether i3 has restarted yet. +while (get_socket_path(0) eq $socketpath) { + sleep 0.1; +} + +$new_tmpdir = $ENV{XDG_RUNTIME_DIR} . '/i3'; + +does_i3_live; + +($nodes, $focus) = get_ws_content($tmp); +is($nodes->[0]->{border}, 'none', 'border still none after restart'); + +exit_gracefully($pid); + +close($outfh); +close($outfh2); done_testing;