add POSIX locking to authkey.c
authorLennart Poettering <lennart@poettering.net>
Mon, 27 Sep 2004 15:40:18 +0000 (15:40 +0000)
committerLennart Poettering <lennart@poettering.net>
Mon, 27 Sep 2004 15:40:18 +0000 (15:40 +0000)
fix esound protocol cpu consumption when finishing a stream

git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@242 fefdeb5f-60dc-0310-8127-8f9354f1896f

polyp/authkey.c
polyp/protocol-esound.c
polyp/util.c
polyp/util.h

index 9b60506ffa1a25476ccc93870a94b3d3bbf4bfbc..1e2edb07dbe4a360c54abed75c043b0e8b16af3c 100644 (file)
 
 #define RANDOM_DEVICE "/dev/urandom"
 
-static int load(const char *fn, void *data, size_t length) {
-    int fd = -1, ret = -1;
+static int generate(int fd, void *data, size_t length) {
+    int random_fd, ret = -1;
     ssize_t r;
-    
-    assert(fn && data && length);
-
-    if ((fd = open(fn, O_RDONLY)) < 0)
-        goto finish;
-
-    if ((r = pa_loop_read(fd, data, length)) < 0 || (size_t) r != length) {
-        ret = -2;
-        goto finish;
-    }
+    assert(fd >= 0 && data && length);
 
-    ret = 0;
-    
-finish:
-    if (fd >= 0)
-        close(fd);
-
-    return ret;
-}
-
-static int generate(const char *fn, void *data, size_t length) {
-    int fd = -1, random_fd = -1, ret = -1;
-    ssize_t r;
-    assert(fn && data && length);
-
-    if ((fd = open(fn, O_WRONLY|O_EXCL|O_CREAT, S_IRUSR | S_IWUSR)) < 0)
-        goto finish;
-    
     if ((random_fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
 
         if ((r = pa_loop_read(random_fd, data, length)) < 0 || (size_t) r != length) {
-            ret = -2;
+            pa_log(__FILE__": failed to read entropy from '%s'\n", RANDOM_DEVICE);
             goto finish;
         }
         
     } else {
         uint8_t *p;
         size_t l;
-        pa_log(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s, falling back to unsecure pseudo RNG.\n", strerror(errno));
+        pa_log(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s"
+               ", falling back to unsecure pseudo RNG.\n", strerror(errno));
 
         srandom(time(NULL));
         
@@ -90,41 +65,81 @@ static int generate(const char *fn, void *data, size_t length) {
             *p = (uint8_t) random();
     }
 
+    lseek(fd, 0, SEEK_SET);
+
     if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) {
-        ret =  -2;
+        pa_log(__FILE__": failed to write cookie file\n");
         goto finish;
     }
 
     ret = 0;
 
 finish:
+
+    if (random_fd >= 0)
+        close(random_fd);
+
+    return ret;
+}
+
+static int load(const char *fn, void *data, size_t length) {
+    int fd = -1;
+    int writable = 1;
+    assert(fn && data && length);
+    int unlock = 0, ret;
+    ssize_t r;
+
+    if ((fd = open(fn, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
+        if (errno != EACCES || (fd = open(fn, O_RDONLY)) < 0) {
+            pa_log(__FILE__": failed to open cookie file '%s'\n", fn);
+            goto finish;
+        } else
+            writable = 0;
+    }
+
+    unlock = pa_lock_file(fd, 1) >= 0;
+
+    if ((r = pa_loop_read(fd, data, length)) < 0) {
+        pa_log(__FILE__": failed to read cookie file '%s'\n", fn);
+        goto finish;
+    }
+
+    if ((size_t) r != length) {
+        
+        if (!writable) {
+            pa_log(__FILE__": unable to write cookie to read only file\n");
+            goto finish;
+        }
+        
+        if (generate(fd, data, length) < 0)
+            goto finish;
+    }
+
+    ret = 0;
+    
+finish:
+
     if (fd >= 0) {
-        if (ret != 0)
-            unlink(fn);
+        
+        if (unlock)
+            pa_lock_file(fd, 0);
+        
         close(fd);
     }
-    if (random_fd >= 0)
-        close(random_fd);
 
     return ret;
 }
 
 int pa_authkey_load(const char *path, void *data, size_t length) {
-    int ret, i;
+    int ret;
 
     assert(path && data && length);
-    
-    for (i = 0; i < 10; i++) {
-        if ((ret = load(path, data, length)) < 0)
-            if (ret == -1 && errno == ENOENT)
-                if ((ret = generate(path,  data, length)) < 0)
-                    if (ret == -1 && errno == EEXIST)
-                        continue;
-        break;
-    }
+
+    ret = load(path, data, length);
 
     if (ret < 0)
-        pa_log(__FILE__": Failed to load authorization key '%s': %s\n", path, (ret == -1) ? strerror(errno) : "file corrupt");
+        pa_log(__FILE__": Failed to load authorization key '%s': %s\n", path,
+               (ret == -1) ? strerror(errno) : "file corrupt");
 
     return ret;
 }
index 799787405cfa761ce13306556647be74aa3c2b1c..4498a750d8c500f10cc43d6c93e0927462237ed8 100644 (file)
@@ -872,7 +872,7 @@ static void do_work(struct connection *c) {
 
     assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
     c->protocol->core->mainloop->defer_enable(c->defer_event, 0);
-
+    
     if (c->dead)
         return;
     
@@ -891,6 +891,7 @@ fail:
     if (c->state == ESD_STREAMING_DATA && c->sink_input) {
         c->dead = 1;
         pa_memblockq_prebuf_disable(c->input_memblockq);
+        c->protocol->core->mainloop->defer_enable(c->defer_event, 0);
     } else
         connection_free(c);
 }
@@ -937,7 +938,9 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk
 
     /* do something */
     assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
-    c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
+
+    if (!c->dead)
+        c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
 
 /*     assert(pa_memblockq_get_length(c->input_memblockq) > 2048); */
 }
@@ -963,7 +966,9 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me
 
     /* do something */
     assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
-    c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
+
+    if (!c->dead)
+        c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
 }
 
 static void source_output_kill_cb(struct pa_source_output *o) {
index 6be6ffe48f543d297807bca50d559bd840e5a1c3..166a9a45cd5371689038e5b10d037d2b8ce97511 100644 (file)
@@ -501,3 +501,20 @@ finish:
     pa_xfree(gids);
     return r;
 }
+
+int pa_lock_file(int fd, int b) {
+
+    struct flock flock;
+
+    flock.l_type = b ? F_WRLCK : F_UNLCK;
+    flock.l_whence = SEEK_SET;
+    flock.l_start = 0;
+    flock.l_len = 0;
+
+    if (fcntl(fd, F_SETLKW, &flock) < 0) {
+        pa_log(__FILE__": %slock failed: %s\n", !b ? "un" : "", strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
index 8f4323f6720d92caf1aea3406eeed3ebddded671..571bb29be440af1d58700223e891d90a1211ad6c 100644 (file)
@@ -68,4 +68,7 @@ int pa_parse_resample_method(const char *string);
 
 int pa_uid_in_group(const char *name, gid_t *gid);
 
+int pa_lock_file(int fd, int b);
+
+
 #endif