1
0
mirror of https://gitlab.gnome.org/GNOME/glib.git synced 2025-09-22 23:53:05 +02:00
Files
build
debian
docs
gio
fam
fen
gvdb
inotify
libasyncns
tests
schema-tests
.gitignore
Makefile.am
actions.c
appinfo-test-gnome.desktop
appinfo-test-notgnome.desktop
appinfo-test.c
appinfo-test.desktop
appinfo-test2.desktop
appinfo.c
application.c
async-close-output-stream.c
buffered-input-stream.c
buffered-output-stream.c
contenttype.c
contexts.c
converter-stream.c
data-input-stream.c
data-output-stream.c
de.po
desktop-app-info.c
echo-server.c
enums.xml.template
file.c
filter-cat.c
filter-streams.c
g-file-info.c
g-file.c
g-icon.c
gdbus-addresses.c
gdbus-connection-flush-helper.c
gdbus-connection.c
gdbus-error.c
gdbus-example-export.c
gdbus-example-own-name.c
gdbus-example-peer.c
gdbus-example-proxy-subclass.c
gdbus-example-server.c
gdbus-example-subtree.c
gdbus-example-unix-fd-client.c
gdbus-example-watch-name.c
gdbus-example-watch-proxy.c
gdbus-exit-on-close.c
gdbus-export.c
gdbus-introspection.c
gdbus-names.c
gdbus-non-socket.c
gdbus-peer.c
gdbus-proxy-well-known-name.c
gdbus-proxy.c
gdbus-serialization.c
gdbus-sessionbus.c
gdbus-sessionbus.h
gdbus-tests.c
gdbus-tests.h
gdbus-testserver.py
gdbus-threading.c
gschema-compile.c
gsettings.c
httpd.c
live-g-file.c
live-g-file.txt
memory-input-stream.c
memory-output-stream.c
network-address.c
org.gtk.test.gschema
org.gtk.test.gschema.xml
proxy.c
readwrite.c
resolver.c
send-data.c
simple-async-result.c
sleepy-stream.c
socket-client.c
socket-common.c
socket-server.c
srvtarget.c
testapp.c
testapps.c
testenum.h
unix-fd.c
unix-streams.c
volumemonitor.c
win32-streams.c
win32
xdgmime
.gitignore
ChangeLog
Makefile.am
abicheck.sh
gaction.c
gaction.h
gactiongroup.c
gactiongroup.h
gappinfo.c
gappinfo.h
gapplication.c
gapplication.h
gasynchelper.c
gasynchelper.h
gasyncinitable.c
gasyncinitable.h
gasyncresult.c
gasyncresult.h
gbufferedinputstream.c
gbufferedinputstream.h
gbufferedoutputstream.c
gbufferedoutputstream.h
gcancellable.c
gcancellable.h
gcharsetconverter.c
gcharsetconverter.h
gcontenttype.c
gcontenttype.h
gcontenttypeprivate.h
gconverter.c
gconverter.h
gconverterinputstream.c
gconverterinputstream.h
gconverteroutputstream.c
gconverteroutputstream.h
gcredentials.c
gcredentials.h
gdatainputstream.c
gdatainputstream.h
gdataoutputstream.c
gdataoutputstream.h
gdbus-bash-completion.sh
gdbus-tool.c
gdbusaddress.c
gdbusaddress.h
gdbusapplication.c
gdbusauth.c
gdbusauth.h
gdbusauthmechanism.c
gdbusauthmechanism.h
gdbusauthmechanismanon.c
gdbusauthmechanismanon.h
gdbusauthmechanismexternal.c
gdbusauthmechanismexternal.h
gdbusauthmechanismsha1.c
gdbusauthmechanismsha1.h
gdbusauthobserver.c
gdbusauthobserver.h
gdbusconnection.c
gdbusconnection.h
gdbuserror.c
gdbuserror.h
gdbusintrospection.c
gdbusintrospection.h
gdbusmessage.c
gdbusmessage.h
gdbusmethodinvocation.c
gdbusmethodinvocation.h
gdbusnameowning.c
gdbusnameowning.h
gdbusnamewatching.c
gdbusnamewatching.h
gdbusprivate.c
gdbusprivate.h
gdbusproxy.c
gdbusproxy.h
gdbusserver.c
gdbusserver.h
gdbusutils.c
gdbusutils.h
gdelayedsettingsbackend.c
gdelayedsettingsbackend.h
gdesktopappinfo.c
gdesktopappinfo.h
gdrive.c
gdrive.h
gdummyfile.c
gdummyfile.h
gdummyproxyresolver.c
gdummyproxyresolver.h
gemblem.c
gemblem.h
gemblemedicon.c
gemblemedicon.h
gfile.c
gfile.h
gfileattribute-priv.h
gfileattribute.c
gfileattribute.h
gfiledescriptorbased.c
gfiledescriptorbased.h
gfileenumerator.c
gfileenumerator.h
gfileicon.c
gfileicon.h
gfileinfo-priv.h
gfileinfo.c
gfileinfo.h
gfileinputstream.c
gfileinputstream.h
gfileiostream.c
gfileiostream.h
gfilemonitor.c
gfilemonitor.h
gfilenamecompleter.c
gfilenamecompleter.h
gfileoutputstream.c
gfileoutputstream.h
gfilterinputstream.c
gfilterinputstream.h
gfilteroutputstream.c
gfilteroutputstream.h
gicon.c
gicon.h
ginetaddress.c
ginetaddress.h
ginetsocketaddress.c
ginetsocketaddress.h
ginitable.c
ginitable.h
ginputstream.c
ginputstream.h
gio-marshal.list
gio-querymodules.c
gio.h
gio.rc.in
gio.symbols
gioenums.h
gioenumtypes.c.template
gioenumtypes.h.template
gioerror.c
gioerror.h
giomodule-priv.h
giomodule.c
giomodule.h
gioscheduler.c
gioscheduler.h
giostream.c
giostream.h
giotypes.h
gkeyfilesettingsbackend.c
gloadableicon.c
gloadableicon.h
glocaldirectorymonitor.c
glocaldirectorymonitor.h
glocalfile.c
glocalfile.h
glocalfileenumerator.c
glocalfileenumerator.h
glocalfileinfo.c
glocalfileinfo.h
glocalfileinputstream.c
glocalfileinputstream.h
glocalfileiostream.c
glocalfileiostream.h
glocalfilemonitor.c
glocalfilemonitor.h
glocalfileoutputstream.c
glocalfileoutputstream.h
glocalvfs.c
glocalvfs.h
gmemoryinputstream.c
gmemoryinputstream.h
gmemoryoutputstream.c
gmemoryoutputstream.h
gmemorysettingsbackend.c
gmemorysettingsbackend.h
gmount.c
gmount.h
gmountoperation.c
gmountoperation.h
gmountprivate.h
gnativevolumemonitor.c
gnativevolumemonitor.h
gnetworkaddress.c
gnetworkaddress.h
gnetworkingprivate.h
gnetworkservice.c
gnetworkservice.h
gnullapplication.c
gnullsettingsbackend.c
gnullsettingsbackend.h
goutputstream.c
goutputstream.h
gpermission.c
gpermission.h
gpollfilemonitor.c
gpollfilemonitor.h
gproxy.c
gproxy.h
gproxyaddress.c
gproxyaddress.h
gproxyaddressenumerator.c
gproxyaddressenumerator.h
gproxyconnection.c
gproxyconnection.h
gproxyresolver.c
gproxyresolver.h
gresolver.c
gresolver.h
gschema-compile.c
gschema.dtd
gseekable.c
gseekable.h
gsettings-bash-completion.sh
gsettings-mapping.c
gsettings-mapping.h
gsettings-tool.c
gsettings.c
gsettings.h
gsettingsbackend.c
gsettingsbackend.h
gsettingsbackendinternal.h
gsettingsschema.c
gsettingsschema.h
gsimpleactiongroup.c
gsimpleactiongroup.h
gsimpleasyncresult.c
gsimpleasyncresult.h
gsimplepermission.c
gsimplepermission.h
gsocket.c
gsocket.h
gsocketaddress.c
gsocketaddress.h
gsocketaddressenumerator.c
gsocketaddressenumerator.h
gsocketclient.c
gsocketclient.h
gsocketconnectable.c
gsocketconnectable.h
gsocketconnection.c
gsocketconnection.h
gsocketcontrolmessage.c
gsocketcontrolmessage.h
gsocketinputstream.c
gsocketinputstream.h
gsocketlistener.c
gsocketlistener.h
gsocketoutputstream.c
gsocketoutputstream.h
gsocketservice.c
gsocketservice.h
gsocks4aproxy.c
gsocks4aproxy.h
gsocks4proxy.c
gsocks4proxy.h
gsocks5proxy.c
gsocks5proxy.h
gsrvtarget.c
gsrvtarget.h
gtcpconnection.c
gtcpconnection.h
gthemedicon.c
gthemedicon.h
gthreadedresolver.c
gthreadedresolver.h
gthreadedsocketservice.c
gthreadedsocketservice.h
gunionvolumemonitor.c
gunionvolumemonitor.h
gunixconnection.c
gunixconnection.h
gunixcredentialsmessage.c
gunixcredentialsmessage.h
gunixfdlist.c
gunixfdlist.h
gunixfdmessage.c
gunixfdmessage.h
gunixinputstream.c
gunixinputstream.h
gunixmount.c
gunixmount.h
gunixmounts.c
gunixmounts.h
gunixoutputstream.c
gunixoutputstream.h
gunixresolver.c
gunixresolver.h
gunixsocketaddress.c
gunixsocketaddress.h
gunixvolume.c
gunixvolume.h
gunixvolumemonitor.c
gunixvolumemonitor.h
gvfs.c
gvfs.h
gvolume.c
gvolume.h
gvolumemonitor.c
gvolumemonitor.h
gwin32appinfo.c
gwin32appinfo.h
gwin32inputstream.c
gwin32inputstream.h
gwin32mount.c
gwin32mount.h
gwin32outputstream.c
gwin32outputstream.h
gwin32resolver.c
gwin32resolver.h
gwin32volumemonitor.c
gwin32volumemonitor.h
gzlibcompressor.c
gzlibcompressor.h
gzlibdecompressor.c
gzlibdecompressor.h
makefile.msc
strinfo.c
glib
gmodule
gobject
gthread
m4macros
po
tests
.gitignore
AUTHORS
COPYING
ChangeLog.pre-1-2
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-14
ChangeLog.pre-2-16
ChangeLog.pre-2-18
ChangeLog.pre-2-2
ChangeLog.pre-2-20
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
HACKING
INSTALL.in
MAINTAINERS
Makefile.am
Makefile.decl
NEWS
NEWS.pre-1-3
README.commits
README.in
README.win32
acglib.m4
acinclude.m4
autogen.sh
config.h.win32.in
configure.ac
gio-2.0-uninstalled.pc.in
gio-2.0.pc.in
gio-unix-2.0-uninstalled.pc.in
gio-unix-2.0.pc.in
gio-windows-2.0.pc.in
glib-2.0-uninstalled.pc.in
glib-2.0.pc.in
glib-gettextize.in
glib-zip.in
gmodule-2.0-uninstalled.pc.in
gmodule-2.0.pc.in
gmodule-export-2.0.pc.in
gmodule-no-export-2.0-uninstalled.pc.in
gmodule-no-export-2.0.pc.in
gobject-2.0-uninstalled.pc.in
gobject-2.0.pc.in
gthread-2.0-uninstalled.pc.in
gthread-2.0.pc.in
makefile.msc
mkinstalldirs
msvc_recommended_pragmas.h
sanity_check
win32-fixup.pl
glib/gio/tests/unix-streams.c
Matthias Clasen b2715bbc5e Fix a possible deadlock
the FdSource was calling g_cancellable_disconnect while holding the
main context lock, which is bad news if the ::cancelled handler is
trying to get that lock to wake up the mainloop...

Bug 586432
2010-08-03 10:41:21 -04:00

257 lines
6.2 KiB
C

/* GLib testing framework examples and tests
* Copyright (C) 2008 Red Hat, Inc
*
* This work is provided "as is"; redistribution and modification
* in whole or in part, in any medium, physical or electronic is
* permitted without restriction.
*
* This work is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* In no event shall the authors or contributors be liable for any
* direct, indirect, incidental, special, exemplary, or consequential
* damages (including, but not limited to, procurement of substitute
* goods or services; loss of use, data, or profits; or business
* interruption) however caused and on any theory of liability, whether
* in contract, strict liability, or tort (including negligence or
* otherwise) arising in any way out of the use of this software, even
* if advised of the possibility of such damage.
*/
#include <gio/gio.h>
#include <gio/gunixinputstream.h>
#include <gio/gunixoutputstream.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define DATA "abcdefghijklmnopqrstuvwxyz"
int writer_pipe[2], reader_pipe[2];
GCancellable *writer_cancel, *reader_cancel, *main_cancel;
GMainLoop *loop;
static gpointer
writer_thread (gpointer user_data)
{
GOutputStream *out;
gssize nwrote, offset;
GError *err = NULL;
out = g_unix_output_stream_new (writer_pipe[1], TRUE);
do
{
g_usleep (10);
offset = 0;
while (offset < (gssize) sizeof (DATA))
{
nwrote = g_output_stream_write (out, DATA + offset,
sizeof (DATA) - offset,
writer_cancel, &err);
if (nwrote <= 0 || err != NULL)
break;
offset += nwrote;
}
g_assert (nwrote > 0 || err != NULL);
}
while (err == NULL);
if (g_cancellable_is_cancelled (writer_cancel))
{
g_cancellable_cancel (main_cancel);
g_object_unref (out);
return NULL;
}
g_warning ("writer: %s", err->message);
g_assert_not_reached ();
}
static gpointer
reader_thread (gpointer user_data)
{
GInputStream *in;
gssize nread = 0, total;
GError *err = NULL;
char buf[sizeof (DATA)];
in = g_unix_input_stream_new (reader_pipe[0], TRUE);
do
{
total = 0;
while (total < (gssize) sizeof (DATA))
{
nread = g_input_stream_read (in, buf + total, sizeof (buf) - total,
reader_cancel, &err);
if (nread <= 0 || err != NULL)
break;
total += nread;
}
if (err)
break;
if (nread == 0)
{
g_assert (err == NULL);
/* pipe closed */
g_object_unref (in);
return NULL;
}
g_assert_cmpstr (buf, ==, DATA);
g_assert (!g_cancellable_is_cancelled (reader_cancel));
}
while (err == NULL);
g_warning ("reader: %s", err->message);
g_assert_not_reached ();
}
char main_buf[sizeof (DATA)];
gssize main_len, main_offset;
static void readable (GObject *source, GAsyncResult *res, gpointer user_data);
static void writable (GObject *source, GAsyncResult *res, gpointer user_data);
static void
do_main_cancel (GOutputStream *out)
{
g_output_stream_close (out, NULL, NULL);
g_main_loop_quit (loop);
}
static void
readable (GObject *source, GAsyncResult *res, gpointer user_data)
{
GInputStream *in = G_INPUT_STREAM (source);
GOutputStream *out = user_data;
GError *err = NULL;
main_len = g_input_stream_read_finish (in, res, &err);
if (g_cancellable_is_cancelled (main_cancel))
{
do_main_cancel (out);
return;
}
g_assert (err == NULL);
main_offset = 0;
g_output_stream_write_async (out, main_buf, main_len,
G_PRIORITY_DEFAULT, main_cancel,
writable, in);
}
static void
writable (GObject *source, GAsyncResult *res, gpointer user_data)
{
GOutputStream *out = G_OUTPUT_STREAM (source);
GInputStream *in = user_data;
GError *err = NULL;
gssize nwrote;
nwrote = g_output_stream_write_finish (out, res, &err);
if (g_cancellable_is_cancelled (main_cancel))
{
do_main_cancel (out);
return;
}
g_assert (err == NULL);
g_assert_cmpint (nwrote, <=, main_len - main_offset);
main_offset += nwrote;
if (main_offset == main_len)
{
g_input_stream_read_async (in, main_buf, sizeof (main_buf),
G_PRIORITY_DEFAULT, main_cancel,
readable, out);
}
else
{
g_output_stream_write_async (out, main_buf + main_offset,
main_len - main_offset,
G_PRIORITY_DEFAULT, main_cancel,
writable, in);
}
}
static gboolean
timeout (gpointer cancellable)
{
g_cancellable_cancel (cancellable);
return FALSE;
}
static void
test_pipe_io (void)
{
GThread *writer, *reader;
GInputStream *in;
GOutputStream *out;
/* Split off two (additional) threads, a reader and a writer. From
* the writer thread, write data synchronously in small chunks,
* which gets read asynchronously by the main thread and then
* written asynchronously to the reader thread, which reads it
* synchronously. Eventually a timeout in the main thread will cause
* it to cancel the writer thread, which will in turn cancel the
* read op in the main thread, which will then close the pipe to
* the reader thread, causing the read op to fail.
*/
g_assert (pipe (writer_pipe) == 0 && pipe (reader_pipe) == 0);
writer_cancel = g_cancellable_new ();
reader_cancel = g_cancellable_new ();
main_cancel = g_cancellable_new ();
writer = g_thread_create (writer_thread, NULL, TRUE, NULL);
reader = g_thread_create (reader_thread, NULL, TRUE, NULL);
in = g_unix_input_stream_new (writer_pipe[0], TRUE);
out = g_unix_output_stream_new (reader_pipe[1], TRUE);
g_input_stream_read_async (in, main_buf, sizeof (main_buf),
G_PRIORITY_DEFAULT, main_cancel,
readable, out);
g_timeout_add (500, timeout, writer_cancel);
loop = g_main_loop_new (NULL, TRUE);
g_main_loop_run (loop);
g_main_loop_unref (loop);
g_thread_join (reader);
g_thread_join (writer);
g_object_unref (main_cancel);
g_object_unref (reader_cancel);
g_object_unref (writer_cancel);
g_object_unref (in);
g_object_unref (out);
}
int
main (int argc,
char *argv[])
{
g_thread_init (NULL);
g_type_init ();
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/unix-streams/pipe-io-test", test_pipe_io);
return g_test_run();
}