diff options
| author | Přemysl Eric Janouch <p@janouch.name> | 2023-06-19 18:57:52 +0200 | 
|---|---|---|
| committer | Přemysl Eric Janouch <p@janouch.name> | 2023-06-19 19:06:37 +0200 | 
| commit | 7e30dfb6f0194d83bc78b67664fbf3231cc8d2bd (patch) | |
| tree | 36e088a34525caa6d7dd35f6818cf6c2ecd88804 | |
| parent | 4cc1baf429bd770937fb31f6aa4ab5b6b4d3d316 (diff) | |
| download | desktop-tools-7e30dfb6f0194d83bc78b67664fbf3231cc8d2bd.tar.gz desktop-tools-7e30dfb6f0194d83bc78b67664fbf3231cc8d2bd.tar.xz desktop-tools-7e30dfb6f0194d83bc78b67664fbf3231cc8d2bd.zip | |
iexec: enable not exitting together with the child
| -rw-r--r-- | iexec.c | 83 | 
1 files changed, 53 insertions, 30 deletions
| @@ -24,20 +24,35 @@  // This can also work on BSD if someone puts in the effort to support kqueue  #include <sys/inotify.h> -static pid_t g_child; -static bool g_restarting = false; -static int g_inotify_fd, g_inotify_wd; +static struct +{ +	pid_t child;                        ///< Watched child or 0 +	bool exits;                         ///< Don't restart child when it exits +	bool respawn;                       ///< Respawn child ASAP +	bool killing;                       ///< Waiting for child to die +	int inotify_fd, inotify_wd; +} +g; +// Note that this program doesn't queue up file-based restarts  static void  handle_inotify_event (const struct inotify_event *e, const char *base)  { -	if (e->wd != g_inotify_wd || strcmp (e->name, base)) +	if (e->wd != g.inotify_wd || strcmp (e->name, base))  		return; -	print_debug ("file changed, killing child"); -	g_restarting = true; -	if (g_child >= 0 && kill (g_child, SIGINT)) -		print_error ("kill: %s", strerror (errno)); +	if (g.child) +	{ +		print_debug ("file changed, killing child"); +		if (kill (g.child, SIGINT)) +			print_error ("kill: %s", strerror (errno)); +		g.killing = true; +	} +	else +	{ +		print_debug ("file changed, respawning"); +		g.respawn = true; +	}  }  static void @@ -46,7 +61,7 @@ handle_file_change (const char *base)  	char buf[4096];  	ssize_t len = 0;  	struct inotify_event *e = NULL; -	while ((len = read (g_inotify_fd, buf, sizeof buf)) > 0) +	while ((len = read (g.inotify_fd, buf, sizeof buf)) > 0)  		for (char *ptr = buf; ptr < buf + len; ptr += sizeof *e + e->len)  			handle_inotify_event ((e = (struct inotify_event *) buf), base);  } @@ -54,9 +69,9 @@ handle_file_change (const char *base)  static void  spawn (char *argv[])  { -	if ((g_child = fork ()) == -1) +	if ((g.child = fork ()) == -1)  		exit_fatal ("fork: %s", strerror (errno)); -	else if (g_child) +	else if (g.child)  		return;  	// A linker can create spurious CLOSE_WRITEs, wait until it's executable @@ -69,23 +84,22 @@ spawn (char *argv[])  }  static bool -check_child_death (char *argv[]) +check_child_death (void)  { -	if (waitpid (g_child, NULL, WNOHANG) != g_child) +	int status = 0; +	if (waitpid (g.child, &status, WNOHANG) != g.child)  		return true; -	if (!g_restarting) +	g.child = 0; +	if (!g.killing)  	{  		print_debug ("child died on its own, not respawning"); -		return false; -	} -	else -	{ -		print_debug ("child died on request, respawning"); -		spawn (argv); -		g_restarting = false; -		return true; +		return g.exits;  	} + +	g.killing = false; +	print_debug ("child died on request, respawning"); +	return g.respawn = true;  }  static void @@ -102,6 +116,7 @@ main (int argc, char *argv[])  	static const struct opt opts[] =  	{  		{ 'f', "file", "PATH", 0, "watch this path rather than the program" }, +		{ 'e', "exits", NULL, 0, "allow the program to exit on its own" },  		{ 'd', "debug", NULL, 0, "run in debug mode" },  		{ 'h', "help", NULL, 0, "display this help and exit" },  		{ 'V', "version", NULL, 0, "output version information and exit" }, @@ -121,6 +136,9 @@ main (int argc, char *argv[])  	case 'f':  		target = optarg;  		break; +	case 'e': +		g.exits = true; +		break;  	case 'd':  		g_debug_mode = true;  		break; @@ -164,25 +182,30 @@ main (int argc, char *argv[])  	char *path = NULL;  	char *dir = dirname ((path = xstrdup (target))); -	if ((g_inotify_fd = inotify_init1 (IN_NONBLOCK)) < 0) +	if ((g.inotify_fd = inotify_init1 (IN_NONBLOCK)) < 0)  		exit_fatal ("inotify_init1: %s", strerror (errno)); -	if ((g_inotify_wd = inotify_add_watch (g_inotify_fd, +	if ((g.inotify_wd = inotify_add_watch (g.inotify_fd,  		dir, IN_MOVED_TO | IN_CLOSE_WRITE)) < 0)  		exit_fatal ("inotify_add_watch: %s", strerror (errno));  	free (path);  	char *base = basename ((path = xstrdup (target))); -	spawn (argv); - +	g.respawn = true;  	do  	{ -		fd_set r; FD_SET (g_inotify_fd, &r); -		(void) pselect (g_inotify_fd + 1, &r, NULL, NULL, NULL, &orig); +		if (g.respawn) +		{ +			spawn (argv); +			g.respawn = false; +		} + +		fd_set r; FD_SET (g.inotify_fd, &r); +		(void) pselect (g.inotify_fd + 1, &r, NULL, NULL, NULL, &orig);  		handle_file_change (base);  	} -	while (check_child_death (argv)); +	while (check_child_death ());  	free (path); -	close (g_inotify_fd); +	xclose (g.inotify_fd);  	return EXIT_SUCCESS;  } | 
