Bug#293214: different locking approach
Michael Vogt
Michael Vogt <mvogt@acm.org>, 293214@bugs.debian.org
Mon, 28 Feb 2005 17:00:35 +0100
--45Z9DzgjV8m4Oswq
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: inline
Hi Gustavo,
I got a bugreport from a user about a left-over lockfile from gksu. I
attached a patch that implements locking in the same way as
apt/synaptic use it. It should be more robust but also it has the
drawback that it will not work on nfs homedirs that don't support
locking and read-only homedirs.
I hope you like the patch.
Cheers,
Michael
--
Linux is not The Answer. Yes is the answer. Linux is The Question. - Neo
--45Z9DzgjV8m4Oswq
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: attachment; filename="gksu-fcntl-locks.diff"
diff -ru orig/gksu-1.2.3/gksu/gksu.c gksu-1.2.3/gksu/gksu.c
--- orig/gksu-1.2.3/gksu/gksu.c 2005-02-28 16:14:17.532791080 +0100
+++ gksu-1.2.3/gksu/gksu.c 2005-02-28 16:51:35.302598360 +0100
@@ -137,11 +137,97 @@
}
}
-void
+pid_t test_lock(const char* fname)
+{
+ int FD = open(fname, 0);
+ if(FD < 0) {
+ if(errno == ENOENT) {
+ // File does not exist
+ return 0;
+ } else {
+ perror("open");
+ return(-1);
+ }
+ }
+ struct flock fl;
+ fl.l_type = F_WRLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ if (fcntl(FD, F_GETLK, &fl) < 0) {
+ g_critical("fcntl error");
+ close(FD);
+ return(-1);
+ }
+ close(FD);
+ // lock is available
+ if(fl.l_type == F_UNLCK)
+ return(0);
+ // file is locked by another process
+ return (fl.l_pid);
+}
+
+int get_lock(const char *File)
+{
+ int FD = open(File,O_RDWR | O_CREAT | O_TRUNC,0640);
+ if (FD < 0)
+ {
+ // Read only .. cant have locking problems there.
+ if (errno == EROFS)
+ {
+ g_warning(_("Not using locking for read only lock file %s"),File);
+ return dup(0); // Need something for the caller to close
+ }
+
+ // Feh.. We do this to distinguish the lock vs open case..
+ errno = EPERM;
+ return -1;
+ }
+ fcntl(FD,F_SETFD, FD_CLOEXEC);
+
+ // Aquire a write lock
+ struct flock fl;
+ fl.l_type = F_WRLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ if (fcntl(FD,F_SETLK,&fl) == -1)
+ {
+ if (errno == ENOLCK)
+ {
+ g_warning(_("Not using locking for nfs mounted lock file %s"), File);
+ return dup(0); // Need something for the caller to close
+ }
+
+ int Tmp = errno;
+ close(FD);
+ errno = Tmp;
+ return -1;
+ }
+
+ return FD;
+}
+
+int
grab_keyboard_and_mouse (GtkWidget *dialog)
{
GdkGrabStatus status;
gint grab_tries = 0;
+ gint lock = -1;
+
+ gchar *fname = g_strdup_printf ("%s/.gksu.lock", getenv ("HOME"));
+ pid_t pid = test_lock (fname);
+
+ if (pid != 0)
+ {
+ g_warning ("Lock taken by pid: %i. Exiting.", pid);
+ exit (0);
+ }
+
+ lock = get_lock(fname);
+ if( lock < 0)
+ g_warning ("Unable to create lock file.");
+ g_free (fname);
gtk_widget_show_all (dialog);
@@ -179,16 +265,21 @@
}
gdk_x11_grab_server();
+ return lock;
}
void
-ungrab_keyboard_and_mouse ()
+ungrab_keyboard_and_mouse (int lock)
{
+
/* Ungrab */
XUngrabServer(GDK_DISPLAY());
gdk_pointer_ungrab(GDK_CURRENT_TIME);
gdk_keyboard_ungrab(GDK_CURRENT_TIME);
gdk_flush();
+
+ close(lock);
+
}
#define GKSU_CONFFILE "/etc/gksu.conf"
@@ -282,12 +373,12 @@
else if (!strcmp ("sudo-mode", key))
{
if (!strcasecmp ("yes", value))
- sudo_mode = FALSE;
+ sudo_mode = TRUE;
}
else if (!strcmp ("prompt", key))
{
if (!strcasecmp ("yes", value))
- prompt = FALSE;
+ prompt = TRUE;
}
g_strfreev (tmp);
@@ -463,7 +554,7 @@
if (force_grab)
grab = TRUE;
- if (prompt && (!grab))
+ if (prompt)
{
GtkWidget *d;
@@ -494,13 +585,14 @@
g_free (msg);
}
+ int lock;
if (grab)
- grab_keyboard_and_mouse (dialog);
+ lock = grab_keyboard_and_mouse (dialog);
retvalue = gtk_dialog_run (GTK_DIALOG(dialog));
gtk_widget_hide (dialog);
if (grab)
- ungrab_keyboard_and_mouse ();
+ ungrab_keyboard_and_mouse (lock);
/*
the user may have pressed cancel or
--45Z9DzgjV8m4Oswq--