LCOV - code coverage report
Current view: top level - basic - async.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 23 26 88.5 %
Date: 2015-07-29 18:47:03 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2013 Lennart Poettering
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include <pthread.h>
      23             : #include <unistd.h>
      24             : 
      25             : #include "async.h"
      26             : #include "log.h"
      27             : #include "util.h"
      28             : 
      29          11 : int asynchronous_job(void* (*func)(void *p), void *arg) {
      30             :         pthread_attr_t a;
      31             :         pthread_t t;
      32             :         int r;
      33             : 
      34             :         /* It kinda sucks that we have to resort to threads to
      35             :          * implement an asynchronous sync(), but well, such is
      36             :          * life.
      37             :          *
      38             :          * Note that issuing this command right before exiting a
      39             :          * process will cause the process to wait for the sync() to
      40             :          * complete. This function hence is nicely asynchronous really
      41             :          * only in long running processes. */
      42             : 
      43          11 :         r = pthread_attr_init(&a);
      44          11 :         if (r > 0)
      45           0 :                 return -r;
      46             : 
      47          11 :         r = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);
      48          11 :         if (r > 0)
      49           0 :                 goto finish;
      50             : 
      51          11 :         r = pthread_create(&t, &a, func, arg);
      52             : 
      53             : finish:
      54          11 :         pthread_attr_destroy(&a);
      55          11 :         return -r;
      56             : }
      57             : 
      58           1 : static void *sync_thread(void *p) {
      59           1 :         sync();
      60           1 :         return NULL;
      61             : }
      62             : 
      63           1 : int asynchronous_sync(void) {
      64           1 :         log_debug("Spawning new thread for sync");
      65             : 
      66           1 :         return asynchronous_job(sync_thread, NULL);
      67             : }
      68             : 
      69           8 : static void *close_thread(void *p) {
      70           8 :         assert_se(close_nointr(PTR_TO_INT(p)) != -EBADF);
      71           8 :         return NULL;
      72             : }
      73             : 
      74          49 : int asynchronous_close(int fd) {
      75             :         int r;
      76             : 
      77             :         /* This is supposed to behave similar to safe_close(), but
      78             :          * actually invoke close() asynchronously, so that it will
      79             :          * never block. Ideally the kernel would have an API for this,
      80             :          * but it doesn't, so we work around it, and hide this as a
      81             :          * far away as we can. */
      82             : 
      83          49 :         if (fd >= 0) {
      84          16 :                 PROTECT_ERRNO;
      85             : 
      86           8 :                 r = asynchronous_job(close_thread, INT_TO_PTR(fd));
      87           8 :                 if (r < 0)
      88           0 :                          assert_se(close_nointr(fd) != -EBADF);
      89             :         }
      90             : 
      91          49 :         return -1;
      92             : }

Generated by: LCOV version 1.11