~ubuntu-branches/ubuntu/quantal/consolekit/quantal-proposed

« back to all changes in this revision

Viewing changes to src/ck-sysdeps-unix.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2010-11-20 18:17:28 UTC
  • mfrom: (0.1.16 sid)
  • Revision ID: james.westby@ubuntu.com-20101120181728-8e5bwe4ttgmk4j41
Tags: 0.4.3-2
Add 01-retry-console-open-on-EIO.patch: As reported in LP: #544139,
ConsoleKit sometimes fails to track the active VT. This particular case
was tracked down to a race condition that happens if you try to open
/dev/console while the current TTY is currently being closed. This yields
an -EIO error, in which case CK should just try again. Thanks Colin Watson
for the patch!

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include <unistd.h>
27
27
#include <string.h>
28
28
#include <errno.h>
 
29
#include <time.h>
29
30
#include <sys/types.h>
30
31
#include <sys/stat.h>
31
32
#include <sys/socket.h>
150
151
{
151
152
        int fd;
152
153
 
 
154
again:
153
155
        fd = open (fnam, O_RDONLY | O_NOCTTY);
154
156
        if (fd < 0 && errno == EACCES)
155
157
                fd = open (fnam, O_WRONLY | O_NOCTTY);
 
158
#ifdef __linux__
 
159
        if (fd < 0 && errno == EIO) {
 
160
                /* Linux can return EIO if the tty is currently closing,
 
161
                 * which can happen if multiple processes are opening and
 
162
                 * closing the console in parallel.  Unfortunately it can
 
163
                 * also return EIO in more serious situations too (see
 
164
                 * https://bugs.launchpad.net/bugs/554172), but there isn't
 
165
                 * much we can do about that since we really need a console
 
166
                 * fd.
 
167
                 */
 
168
                struct timespec ts = { 0, 100000000 }; /* 0.1 seconds */
 
169
                nanosleep (&ts, NULL);
 
170
                goto again;
 
171
        }
 
172
#endif
156
173
 
157
174
        if (fd < 0)
158
175
                return -1;
296
313
        return ret;
297
314
}
298
315
 
299
 
#ifdef VT_WAITEVENT
300
 
gboolean
301
 
ck_wait_for_console_switch (int   console_fd,
302
 
                            guint *num)
303
 
{
304
 
        gboolean ret;
305
 
        int      res;
306
 
        struct vt_event vt;
307
 
 
308
 
        g_assert (console_fd != -1);
309
 
 
310
 
 again:
311
 
        ret = FALSE;
312
 
        errno = 0;
313
 
        vt.event = VT_EVENT_SWITCH;
314
 
        vt.oldev = *num;
315
 
        res = ioctl (console_fd, VT_WAITEVENT, &vt);
316
 
 
317
 
        if (res == ERROR) {
318
 
                const char *errmsg;
319
 
 
320
 
                errmsg = g_strerror (errno);
321
 
 
322
 
                if (errno == EINTR) {
323
 
                        g_debug ("Interrupted waiting for native console event: %s",
324
 
                                  errmsg);
325
 
                       goto again;
326
 
                } else if (errno == ENOTSUP) {
327
 
                        g_debug ("Console event not supported on this system");
328
 
                } else {
329
 
                        g_warning ("Error waiting for native console event: %s",
330
 
                                   errmsg);
331
 
                }
332
 
                goto out;
333
 
        }
334
 
 
335
 
        ret = TRUE;
336
 
        *num = vt.newev;
337
 
 
338
 
 out:
339
 
        return ret;
340
 
}
341
 
#endif
342
 
 
343
316
gboolean
344
317
ck_activate_console_num (int   console_fd,
345
318
                         guint num)