diff options
author | Werner Koch <[email protected]> | 2014-04-15 14:40:48 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2014-04-30 19:14:28 +0000 |
commit | 8416c875a729426eae05ed1ca9f1ebcb933c246a (patch) | |
tree | 1fcc94bb74e17505af4d27fe6dbbcc361d137044 | |
parent | estream: Fix deadlock in es_fileno. (diff) | |
download | gnupg-8416c875a729426eae05ed1ca9f1ebcb933c246a.tar.gz gnupg-8416c875a729426eae05ed1ca9f1ebcb933c246a.zip |
estream: Implement "samethread" mode keyword.
* src/estream.c (estream_internal): Add field SAMETHREAD.
(init_stream_lock, lock_stream, trylock_stream, unlock_stream): Use it.
(parse_mode): Add arg SAMETHREAD and parse that keyword.
(es_initialize): Rename to ...
(init_stream_obj): this. Add arg SAMETHREAD.
(es_create): Add arg SAMETHREAD. Call init_stream_lock after
init_stream_obj.
(doreadline): Call es_create with samethread flag.
(es_fopen, es_mopen, es_fopenmem, es_fopencookie, do_fdopen)
(do_fpopen, do_w32open): Implement "samethread" keyword.
(es_freopen): Take samthread flag from old stream.
(es_tmpfile): Call es)_create w/o samethread.
--
Note: Unfortunately es_tmpfile has no mode arg so that we can't use
samethread.
Diffstat (limited to '')
-rw-r--r-- | common/estream.c | 161 |
1 files changed, 107 insertions, 54 deletions
diff --git a/common/estream.c b/common/estream.c index a20d6d4e3..34726a3e4 100644 --- a/common/estream.c +++ b/common/estream.c @@ -1,5 +1,6 @@ /* estream.c - Extended Stream I/O Library - * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 g10 Code GmbH + * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011, + * 2014 g10 Code GmbH * * This file is part of Libestream. * @@ -221,6 +222,7 @@ struct estream_internal unsigned int is_stdstream:1; /* This is a standard stream. */ unsigned int stdstream_fd:2; /* 0, 1 or 2 for a standard stream. */ unsigned int printable_fname_inuse: 1; /* es_fname_get has been used. */ + unsigned int samethread: 1; /* The "samethread" mode keyword. */ size_t print_ntotal; /* Bytes written from in print_writer. */ notify_list_t onclose; /* On close notify function list. */ }; @@ -359,9 +361,14 @@ init_stream_lock (estream_t ES__RESTRICT stream) #ifdef HAVE_NPTH int rc; - dbg_lock_1 ("enter init_stream_lock for %p\n", stream); - rc = npth_mutex_init (&stream->intern->lock, NULL); - dbg_lock_2 ("leave init_stream_lock for %p: rc=%d\n", stream, rc); + if (!stream->intern->samethread) + { + dbg_lock_1 ("enter init_stream_lock for %p\n", stream); + rc = npth_mutex_init (&stream->intern->lock, NULL); + dbg_lock_2 ("leave init_stream_lock for %p: rc=%d\n", stream, rc); + } + else + rc = 0; return rc; #else (void)stream; @@ -374,9 +381,12 @@ static void lock_stream (estream_t ES__RESTRICT stream) { #ifdef HAVE_NPTH - dbg_lock_1 ("enter lock_stream for %p\n", stream); - npth_mutex_lock (&stream->intern->lock); - dbg_lock_1 ("leave lock_stream for %p\n", stream); + if (!stream->intern->samethread) + { + dbg_lock_1 ("enter lock_stream for %p\n", stream); + npth_mutex_lock (&stream->intern->lock); + dbg_lock_1 ("leave lock_stream for %p\n", stream); + } #else (void)stream; #endif @@ -389,9 +399,14 @@ trylock_stream (estream_t ES__RESTRICT stream) #ifdef HAVE_NPTH int rc; - dbg_lock_1 ("enter trylock_stream for %p\n", stream); - rc = npth_mutex_trylock (&stream->intern->lock)? 0 : -1; - dbg_lock_2 ("leave trylock_stream for %p: rc=%d\n", stream, rc); + if (!stream->intern->samethread) + { + dbg_lock_1 ("enter trylock_stream for %p\n", stream); + rc = npth_mutex_trylock (&stream->intern->lock)? 0 : -1; + dbg_lock_2 ("leave trylock_stream for %p: rc=%d\n", stream, rc); + } + else + rc = 0; return rc; #else (void)stream; @@ -404,9 +419,12 @@ static void unlock_stream (estream_t ES__RESTRICT stream) { #ifdef HAVE_NPTH - dbg_lock_1 ("enter unlock_stream for %p\n", stream); - npth_mutex_unlock (&stream->intern->lock); - dbg_lock_1 ("leave unlock_stream for %p\n", stream); + if (!stream->intern->samethread) + { + dbg_lock_1 ("enter unlock_stream for %p\n", stream); + npth_mutex_unlock (&stream->intern->lock); + dbg_lock_1 ("leave unlock_stream for %p\n", stream); + } #else (void)stream; #endif @@ -1478,29 +1496,40 @@ func_file_create (void **cookie, int *filedes, defined mode flags keyword parameters are supported. These are key/value pairs delimited by comma and optional white spaces. Keywords and values may not contain a comma or white space; unknown - keyword are skipped. The only supported keyword is mode; for - example: + keywords are skipped. Supported keywords are: + + mode=<string> + + Creates a file and gives the new file read and write permissions + for the user and read permission for the group. The format of + the string is the same as shown by the -l option of the ls(1) + command. However the first letter must be a dash and it is + allowed to leave out trailing dashes. If this keyword parameter + is not given the default mode for creating files is "-rw-rw-r--" + (664). Note that the system still applies the current umask to + the mode when crating a file. Example: + + "wb,mode=-rw-r--" + + samethread - "wb,mode=-rw-r--" + Assumes that the object is only used by the creating thread and + disables any internal locking. This keyword is also found on + IBM systems. - Creates a file and gives the new file read and write permissions - for the user and read permission for the group. The format of the - string is the same as shown by the -l option of the ls(1) command. - However the first letter must be a dash and it is allowed to leave - out trailing dashes. If this keyword parameter is not given the - default mode for creating files is "-rw-rw-r--" (664). Note that - the system still applies the current umask to the mode when crating - a file. Note: R_CMODE is optional because is only required by functions which are able to creat a file. */ static int parse_mode (const char *modestr, - unsigned int *modeflags, unsigned int *r_cmode) + unsigned int *modeflags, int *samethread, + unsigned int *r_cmode) { unsigned int omode, oflags, cmode; int got_cmode = 0; + *samethread = 0; + switch (*modestr) { case 'r': @@ -1573,6 +1602,16 @@ parse_mode (const char *modestr, return -1; } } + else if (!strncmp (modestr, "samethread", 10)) + { + modestr += 10; + if (*modestr && !strchr (" \t,", *modestr)) + { + _set_errno (EINVAL); + return -1; + } + *samethread = 1; + } } if (!got_cmode) cmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); @@ -1712,10 +1751,10 @@ es_empty (estream_t stream) /* Initialize STREAM. */ static void -es_initialize (estream_t stream, - void *cookie, es_syshd_t *syshd, - es_cookie_io_functions_t functions, - unsigned int modeflags) +init_stream_obj (estream_t stream, + void *cookie, es_syshd_t *syshd, + es_cookie_io_functions_t functions, + unsigned int modeflags, int samethread) { stream->intern->cookie = cookie; stream->intern->opaque = NULL; @@ -1735,6 +1774,7 @@ es_initialize (estream_t stream, stream->intern->deallocate_buffer = 0; stream->intern->printable_fname = NULL; stream->intern->printable_fname_inuse = 0; + stream->intern->samethread = !!samethread; stream->intern->onclose = NULL; stream->data_len = 0; @@ -1784,7 +1824,7 @@ es_deinitialize (estream_t stream) static int es_create (estream_t *stream, void *cookie, es_syshd_t *syshd, es_cookie_io_functions_t functions, unsigned int modeflags, - int with_locked_list) + int samethread, int with_locked_list) { estream_internal_t stream_internal_new; estream_t stream_new; @@ -1813,8 +1853,8 @@ es_create (estream_t *stream, void *cookie, es_syshd_t *syshd, stream_new->unread_buffer_size = sizeof (stream_internal_new->unread_buffer); stream_new->intern = stream_internal_new; + init_stream_obj (stream_new, cookie, syshd, functions, modeflags, samethread); init_stream_lock (stream_new); - es_initialize (stream_new, cookie, syshd, functions, modeflags); err = do_list_add (stream_new, with_locked_list); if (err) @@ -2406,7 +2446,7 @@ doreadline (estream_t ES__RESTRICT stream, size_t max_length, memset (&syshd, 0, sizeof syshd); err = es_create (&line_stream, line_stream_cookie, &syshd, - estream_functions_mem, O_RDWR, 0); + estream_functions_mem, O_RDWR, 1, 0); if (err) goto out; @@ -2667,7 +2707,7 @@ estream_t es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode) { unsigned int modeflags, cmode; - int create_called; + int samethread, create_called; estream_t stream; void *cookie; int err; @@ -2678,7 +2718,7 @@ es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode) cookie = NULL; create_called = 0; - err = parse_mode (mode, &modeflags, &cmode); + err = parse_mode (mode, &modeflags, &samethread, &cmode); if (err) goto out; @@ -2690,7 +2730,8 @@ es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode) syshd.u.fd = fd; create_called = 1; - err = es_create (&stream, cookie, &syshd, estream_functions_fd, modeflags, 0); + err = es_create (&stream, cookie, &syshd, estream_functions_fd, modeflags, + samethread, 0); if (err) goto out; @@ -2731,10 +2772,11 @@ es_mopen (void *ES__RESTRICT data, size_t data_n, size_t data_len, estream_t stream = NULL; void *cookie = NULL; unsigned int modeflags; + int samethread; int err; es_syshd_t syshd; - err = parse_mode (mode, &modeflags, NULL); + err = parse_mode (mode, &modeflags, &samethread, NULL); if (err) goto out; @@ -2747,7 +2789,7 @@ es_mopen (void *ES__RESTRICT data, size_t data_n, size_t data_len, memset (&syshd, 0, sizeof syshd); create_called = 1; err = es_create (&stream, cookie, &syshd, - estream_functions_mem, modeflags, 0); + estream_functions_mem, modeflags, samethread, 0); out: @@ -2763,13 +2805,14 @@ estream_t es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode) { unsigned int modeflags; + int samethread; estream_t stream = NULL; void *cookie = NULL; es_syshd_t syshd; /* Memory streams are always read/write. We use MODE only to get the append flag. */ - if (parse_mode (mode, &modeflags, NULL)) + if (parse_mode (mode, &modeflags, &samethread, NULL)) return NULL; modeflags |= O_RDWR; @@ -2780,7 +2823,8 @@ es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode) return NULL; memset (&syshd, 0, sizeof syshd); - if (es_create (&stream, cookie, &syshd, estream_functions_mem, modeflags, 0)) + if (es_create (&stream, cookie, &syshd, estream_functions_mem, modeflags, + samethread, 0)) (*estream_functions_mem.func_close) (cookie); if (stream) @@ -2830,6 +2874,7 @@ es_fopencookie (void *ES__RESTRICT cookie, es_cookie_io_functions_t functions) { unsigned int modeflags; + int samethread; estream_t stream; int err; es_syshd_t syshd; @@ -2837,12 +2882,13 @@ es_fopencookie (void *ES__RESTRICT cookie, stream = NULL; modeflags = 0; - err = parse_mode (mode, &modeflags, NULL); + err = parse_mode (mode, &modeflags, &samethread, NULL); if (err) goto out; memset (&syshd, 0, sizeof syshd); - err = es_create (&stream, cookie, &syshd, functions, modeflags, 0); + err = es_create (&stream, cookie, &syshd, functions, modeflags, + samethread, 0); if (err) goto out; @@ -2856,7 +2902,7 @@ estream_t do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list) { unsigned int modeflags; - int create_called; + int samethread, create_called; estream_t stream; void *cookie; int err; @@ -2866,7 +2912,7 @@ do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list) cookie = NULL; create_called = 0; - err = parse_mode (mode, &modeflags, NULL); + err = parse_mode (mode, &modeflags, &samethread, NULL); if (err) goto out; @@ -2878,7 +2924,7 @@ do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list) syshd.u.fd = filedes; create_called = 1; err = es_create (&stream, cookie, &syshd, estream_functions_fd, - modeflags, with_locked_list); + modeflags, samethread, with_locked_list); out: if (err && create_called) @@ -2906,7 +2952,7 @@ estream_t do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list) { unsigned int modeflags, cmode; - int create_called; + int samethread, create_called; estream_t stream; void *cookie; int err; @@ -2916,7 +2962,7 @@ do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list) cookie = NULL; create_called = 0; - err = parse_mode (mode, &modeflags, &cmode); + err = parse_mode (mode, &modeflags, &samethread, &cmode); if (err) goto out; @@ -2930,7 +2976,7 @@ do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list) syshd.u.fd = fp? fileno (fp): -1; create_called = 1; err = es_create (&stream, cookie, &syshd, estream_functions_fp, - modeflags, with_locked_list); + modeflags, samethread, with_locked_list); out: @@ -2971,13 +3017,14 @@ do_w32open (HANDLE hd, const char *mode, int no_close, int with_locked_list) { unsigned int modeflags, cmode; + int samethread; int create_called = 0; estream_t stream = NULL; void *cookie = NULL; int err; es_syshd_t syshd; - err = parse_mode (mode, &modeflags, &cmode); + err = parse_mode (mode, &modeflags, &samethread, &cmode); if (err) goto leave; @@ -2989,7 +3036,7 @@ do_w32open (HANDLE hd, const char *mode, syshd.u.handle = hd; create_called = 1; err = es_create (&stream, cookie, &syshd, estream_functions_w32, - modeflags, with_locked_list); + modeflags, samethread, with_locked_list); leave: if (err && create_called) @@ -3127,7 +3174,8 @@ _es_get_std_stream (int fd) return stream; } - +/* Note: A "samethread" keyword given in "mode" is ignored and the + value used by STREAM is used instead. */ estream_t es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode, estream_t ES__RESTRICT stream) @@ -3137,7 +3185,7 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode, if (path) { unsigned int modeflags, cmode; - int create_called; + int dummy, samethread, create_called; void *cookie; int fd; es_syshd_t syshd; @@ -3145,13 +3193,16 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode, cookie = NULL; create_called = 0; + samethread = stream->intern->samethread; + lock_stream (stream); es_deinitialize (stream); - err = parse_mode (mode, &modeflags, &cmode); + err = parse_mode (mode, &modeflags, &dummy, &cmode); if (err) goto leave; + (void)dummy; err = func_file_create (&cookie, &fd, path, modeflags, cmode); if (err) @@ -3160,7 +3211,8 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode, syshd.type = ES_SYSHD_FD; syshd.u.fd = fd; create_called = 1; - es_initialize (stream, cookie, &syshd, estream_functions_fd, modeflags); + init_stream_obj (stream, cookie, &syshd, estream_functions_fd, + modeflags, samethread); leave: @@ -4186,7 +4238,8 @@ es_tmpfile (void) syshd.type = ES_SYSHD_FD; syshd.u.fd = fd; create_called = 1; - err = es_create (&stream, cookie, &syshd, estream_functions_fd, modeflags, 0); + err = es_create (&stream, cookie, &syshd, estream_functions_fd, modeflags, + 0, 0); out: if (err) |