Commit 3fc6d56d authored by Michael Natterer's avatar Michael Natterer 😴 Committed by Michael Natterer

After a weekend of extensive mail exchange with the signal crew, we

2000-05-14  Michael Natterer  <mitch@gimp.org>

	After a weekend of extensive mail exchange with the signal crew,
	we finally found that #2742 is not a Gimp bug but a real OSF/1
	bug. OSF/1 does _not_ reliably restart read() and write() calls
	on certain slow devices (pipes).

	* libgimp/gimpwire.[ch]: guard all read/write calls on the wire
	with loops checking for EINTR. This has to be done "manually"
	as glib's GIOChannels return G_IO_ERROR_UNKNOWN on the occurence
	of EINTR (which is a bug, too).
	s/int/gboolean and minor cleanups while I was on it (not changing
	any logic).

	This fix depends on the current (broken) state of the GIOChannel
	implementation and is scheduled for removal as soon as glib
	behaves nicely here.

	Left SA_RESTART there for the moment in app/main.c. See it as
	defensive programming or just my fear to change two #2742-related
	places at the same time. We might choose to remove SA_RESTART
	later. Many thanks again to Austin, Garry and Tim.
parent d28f0809
2000-05-14 Michael Natterer <mitch@gimp.org>
After a weekend of extensive mail exchange with the signal crew,
we finally found that #2742 is not a Gimp bug but a real OSF/1
bug. OSF/1 does _not_ reliably restart read() and write() calls
on certain slow devices (pipes).
* libgimp/gimpwire.[ch]: guard all read/write calls on the wire
with loops checking for EINTR. This has to be done "manually"
as glib's GIOChannels return G_IO_ERROR_UNKNOWN on the occurence
of EINTR (which is a bug, too).
s/int/gboolean and minor cleanups while I was on it (not changing
any logic).
This fix depends on the current (broken) state of the GIOChannel
implementation and is scheduled for removal as soon as glib
behaves nicely here.
Left SA_RESTART there for the moment in app/main.c. See it as
defensive programming or just my fear to change two #2742-related
places at the same time. We might choose to remove SA_RESTART
later. Many thanks again to Austin, Garry and Tim.
2000-05-12 Sven Neumann <sven@gimp.org>
* gimpdrawable.c: enabled the (commented out) signal
......
......@@ -5,8 +5,8 @@
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
*
* This library 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. See the GNU
* Library General Public License for more details.
......@@ -43,24 +43,24 @@ typedef struct _WireHandler WireHandler;
struct _WireHandler
{
guint32 type;
WireReadFunc read_func;
WireWriteFunc write_func;
guint32 type;
WireReadFunc read_func;
WireWriteFunc write_func;
WireDestroyFunc destroy_func;
};
static void wire_init (void);
static guint wire_hash (guint32 *key);
static gint wire_compare (guint32 *a,
guint32 *b);
static void wire_init (void);
static guint wire_hash (guint32 *key);
static gboolean wire_compare (guint32 *a,
guint32 *b);
static GHashTable *wire_ht = NULL;
static WireIOFunc wire_read_func = NULL;
static WireIOFunc wire_write_func = NULL;
static WireFlushFunc wire_flush_func = NULL;
static int wire_error_val = FALSE;
static GHashTable *wire_ht = NULL;
static WireIOFunc wire_read_func = NULL;
static WireIOFunc wire_write_func = NULL;
static WireFlushFunc wire_flush_func = NULL;
static gboolean wire_error_val = FALSE;
void
......@@ -78,9 +78,9 @@ wire_register (guint32 type,
if (!handler)
handler = g_new (WireHandler, 1);
handler->type = type;
handler->read_func = read_func;
handler->write_func = write_func;
handler->type = type;
handler->read_func = read_func;
handler->write_func = write_func;
handler->destroy_func = destroy_func;
g_hash_table_insert (wire_ht, &handler->type, handler);
......@@ -104,7 +104,7 @@ wire_set_flusher (WireFlushFunc flush_func)
wire_flush_func = flush_func;
}
int
gboolean
wire_read (GIOChannel *channel,
guint8 *buf,
gulong count)
......@@ -121,14 +121,17 @@ wire_read (GIOChannel *channel,
else
{
GIOError error;
guint bytes;
guint bytes;
while (count > 0)
{
do {
bytes = 0;
error = g_io_channel_read (channel, (char*) buf, count, &bytes);
} while (error == G_IO_ERROR_AGAIN);
do
{
bytes = 0;
error = g_io_channel_read (channel, (char*) buf, count, &bytes);
}
while ((error == G_IO_ERROR_AGAIN) ||
(error == G_IO_ERROR_UNKNOWN && errno == EINTR));
if (error != G_IO_ERROR_NONE)
{
......@@ -137,7 +140,7 @@ wire_read (GIOChannel *channel,
return FALSE;
}
if (bytes == 0)
if (bytes == 0)
{
g_warning ("%s: wire_read: unexpected EOF", g_get_prgname ());
wire_error_val = TRUE;
......@@ -152,7 +155,7 @@ wire_read (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_write (GIOChannel *channel,
guint8 *buf,
gulong count)
......@@ -169,14 +172,17 @@ wire_write (GIOChannel *channel,
else
{
GIOError error;
guint bytes;
guint bytes;
while (count > 0)
{
do {
bytes = 0;
error = g_io_channel_write (channel, (char*) buf, count, &bytes);
} while (error == G_IO_ERROR_AGAIN);
do
{
bytes = 0;
error = g_io_channel_write (channel, (char*) buf, count, &bytes);
}
while ((error == G_IO_ERROR_AGAIN) ||
(error == G_IO_ERROR_UNKNOWN && errno == EINTR));
if (error != G_IO_ERROR_NONE)
{
......@@ -193,27 +199,28 @@ wire_write (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_flush (GIOChannel *channel)
{
if (wire_flush_func)
return (* wire_flush_func) (channel);
return FALSE;
}
int
wire_error ()
gboolean
wire_error (void)
{
return wire_error_val;
}
void
wire_clear_error ()
wire_clear_error (void)
{
wire_error_val = FALSE;
}
int
gboolean
wire_read_msg (GIOChannel *channel,
WireMessage *msg)
{
......@@ -234,7 +241,7 @@ wire_read_msg (GIOChannel *channel,
return !wire_error_val;
}
int
gboolean
wire_write_msg (GIOChannel *channel,
WireMessage *msg)
{
......@@ -267,7 +274,7 @@ wire_destroy (WireMessage *msg)
(* handler->destroy_func) (msg);
}
int
gboolean
wire_read_int32 (GIOChannel *channel,
guint32 *data,
gint count)
......@@ -287,7 +294,7 @@ wire_read_int32 (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_read_int16 (GIOChannel *channel,
guint16 *data,
gint count)
......@@ -307,7 +314,7 @@ wire_read_int16 (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_read_int8 (GIOChannel *channel,
guint8 *data,
gint count)
......@@ -315,13 +322,13 @@ wire_read_int8 (GIOChannel *channel,
return wire_read (channel, data, count);
}
int
gboolean
wire_read_double (GIOChannel *channel,
gdouble *data,
gint count)
{
char *str;
int i;
gchar *str;
gint i;
for (i = 0; i < count; i++)
{
......@@ -334,13 +341,13 @@ wire_read_double (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_read_string (GIOChannel *channel,
gchar **data,
gint count)
{
guint32 tmp;
int i;
gint i;
for (i = 0; i < count; i++)
{
......@@ -365,13 +372,13 @@ wire_read_string (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_write_int32 (GIOChannel *channel,
guint32 *data,
gint count)
{
guint32 tmp;
int i;
gint i;
if (count > 0)
{
......@@ -386,13 +393,13 @@ wire_write_int32 (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_write_int16 (GIOChannel *channel,
guint16 *data,
gint count)
{
guint16 tmp;
int i;
gint i;
if (count > 0)
{
......@@ -407,7 +414,7 @@ wire_write_int16 (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_write_int8 (GIOChannel *channel,
guint8 *data,
gint count)
......@@ -415,18 +422,19 @@ wire_write_int8 (GIOChannel *channel,
return wire_write (channel, data, count);
}
int
gboolean
wire_write_double (GIOChannel *channel,
gdouble *data,
gint count)
{
gchar *t, buf[128];
int i;
gchar *t;
gchar buf[128];
gint i;
t = buf;
for (i = 0; i < count; i++)
{
sprintf (buf, "%0.50e", data[i]);
g_snprintf (buf, sizeof (buf), "%0.50e", data[i]);
if (!wire_write_string (channel, &t, 1))
return FALSE;
}
......@@ -434,13 +442,13 @@ wire_write_double (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_write_string (GIOChannel *channel,
gchar **data,
gint count)
{
guint32 tmp;
int i;
gint i;
for (i = 0; i < count; i++)
{
......@@ -460,7 +468,7 @@ wire_write_string (GIOChannel *channel,
}
static void
wire_init ()
wire_init (void)
{
if (!wire_ht)
{
......@@ -475,7 +483,7 @@ wire_hash (guint32 *key)
return *key;
}
static gint
static gboolean
wire_compare (guint32 *a,
guint32 *b)
{
......
/* LIBGIMP - The GIMP Library
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software; you can redistribute it and/or
......@@ -26,70 +26,80 @@
typedef struct _WireMessage WireMessage;
typedef void (* WireReadFunc) (GIOChannel *channel, WireMessage *msg);
typedef void (* WireWriteFunc) (GIOChannel *channel, WireMessage *msg);
typedef void (* WireDestroyFunc) (WireMessage *msg);
typedef int (* WireIOFunc) (GIOChannel *channel, guint8 *buf, gulong count);
typedef int (* WireFlushFunc) (GIOChannel *channel);
typedef void (* WireReadFunc) (GIOChannel *channel,
WireMessage *msg);
typedef void (* WireWriteFunc) (GIOChannel *channel,
WireMessage *msg);
typedef void (* WireDestroyFunc) (WireMessage *msg);
typedef gboolean (* WireIOFunc) (GIOChannel *channel,
guint8 *buf,
gulong count);
typedef gboolean (* WireFlushFunc) (GIOChannel *channel);
struct _WireMessage
{
guint32 type;
guint32 type;
gpointer data;
};
void wire_register (guint32 type,
WireReadFunc read_func,
WireWriteFunc write_func,
WireDestroyFunc destroy_func);
void wire_set_reader (WireIOFunc read_func);
void wire_set_writer (WireIOFunc write_func);
void wire_set_flusher (WireFlushFunc flush_func);
int wire_read (GIOChannel *channel,
guint8 *buf,
gulong count);
int wire_write (GIOChannel *channel,
guint8 *buf,
gulong count);
int wire_flush (GIOChannel *channel);
int wire_error (void);
void wire_clear_error (void);
int wire_read_msg (GIOChannel *channel,
WireMessage *msg);
int wire_write_msg (GIOChannel *channel,
WireMessage *msg);
void wire_destroy (WireMessage *msg);
int wire_read_int32 (GIOChannel *channel,
guint32 *data,
gint count);
int wire_read_int16 (GIOChannel *channel,
guint16 *data,
gint count);
int wire_read_int8 (GIOChannel *channel,
guint8 *data,
gint count);
int wire_read_double (GIOChannel *channel,
gdouble *data,
gint count);
int wire_read_string (GIOChannel *channel,
gchar **data,
gint count);
int wire_write_int32 (GIOChannel *channel,
guint32 *data,
gint count);
int wire_write_int16 (GIOChannel *channel,
guint16 *data,
gint count);
int wire_write_int8 (GIOChannel *channel,
guint8 *data,
gint count);
int wire_write_double (GIOChannel *channel,
gdouble *data,
gint count);
int wire_write_string (GIOChannel *channel,
gchar **data,
gint count);
void wire_register (guint32 type,
WireReadFunc read_func,
WireWriteFunc write_func,
WireDestroyFunc destroy_func);
void wire_set_reader (WireIOFunc read_func);
void wire_set_writer (WireIOFunc write_func);
void wire_set_flusher (WireFlushFunc flush_func);
gboolean wire_read (GIOChannel *channel,
guint8 *buf,
gulong count);
gboolean wire_write (GIOChannel *channel,
guint8 *buf,
gulong count);
gboolean wire_flush (GIOChannel *channel);
gboolean wire_error (void);
void wire_clear_error (void);
gboolean wire_read_msg (GIOChannel *channel,
WireMessage *msg);
gboolean wire_write_msg (GIOChannel *channel,
WireMessage *msg);
void wire_destroy (WireMessage *msg);
gboolean wire_read_int32 (GIOChannel *channel,
guint32 *data,
gint count);
gboolean wire_read_int16 (GIOChannel *channel,
guint16 *data,
gint count);
gboolean wire_read_int8 (GIOChannel *channel,
guint8 *data,
gint count);
gboolean wire_read_double (GIOChannel *channel,
gdouble *data,
gint count);
gboolean wire_read_string (GIOChannel *channel,
gchar **data,
gint count);
gboolean wire_write_int32 (GIOChannel *channel,
guint32 *data,
gint count);
gboolean wire_write_int16 (GIOChannel *channel,
guint16 *data,
gint count);
gboolean wire_write_int8 (GIOChannel *channel,
guint8 *data,
gint count);
gboolean wire_write_double (GIOChannel *channel,
gdouble *data,
gint count);
gboolean wire_write_string (GIOChannel *channel,
gchar **data,
gint count);
#endif /* __GIMP_WIRE_H__ */
......@@ -5,8 +5,8 @@
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
*
* This library 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. See the GNU
* Library General Public License for more details.
......@@ -43,24 +43,24 @@ typedef struct _WireHandler WireHandler;
struct _WireHandler
{
guint32 type;
WireReadFunc read_func;
WireWriteFunc write_func;
guint32 type;
WireReadFunc read_func;
WireWriteFunc write_func;
WireDestroyFunc destroy_func;
};
static void wire_init (void);
static guint wire_hash (guint32 *key);
static gint wire_compare (guint32 *a,
guint32 *b);
static void wire_init (void);
static guint wire_hash (guint32 *key);
static gboolean wire_compare (guint32 *a,
guint32 *b);
static GHashTable *wire_ht = NULL;
static WireIOFunc wire_read_func = NULL;
static WireIOFunc wire_write_func = NULL;
static WireFlushFunc wire_flush_func = NULL;
static int wire_error_val = FALSE;
static GHashTable *wire_ht = NULL;
static WireIOFunc wire_read_func = NULL;
static WireIOFunc wire_write_func = NULL;
static WireFlushFunc wire_flush_func = NULL;
static gboolean wire_error_val = FALSE;
void
......@@ -78,9 +78,9 @@ wire_register (guint32 type,
if (!handler)
handler = g_new (WireHandler, 1);
handler->type = type;
handler->read_func = read_func;
handler->write_func = write_func;
handler->type = type;
handler->read_func = read_func;
handler->write_func = write_func;
handler->destroy_func = destroy_func;
g_hash_table_insert (wire_ht, &handler->type, handler);
......@@ -104,7 +104,7 @@ wire_set_flusher (WireFlushFunc flush_func)
wire_flush_func = flush_func;
}
int
gboolean
wire_read (GIOChannel *channel,
guint8 *buf,
gulong count)
......@@ -121,14 +121,17 @@ wire_read (GIOChannel *channel,
else
{
GIOError error;
guint bytes;
guint bytes;
while (count > 0)
{
do {
bytes = 0;
error = g_io_channel_read (channel, (char*) buf, count, &bytes);
} while (error == G_IO_ERROR_AGAIN);
do
{
bytes = 0;
error = g_io_channel_read (channel, (char*) buf, count, &bytes);
}
while ((error == G_IO_ERROR_AGAIN) ||
(error == G_IO_ERROR_UNKNOWN && errno == EINTR));
if (error != G_IO_ERROR_NONE)
{
......@@ -137,7 +140,7 @@ wire_read (GIOChannel *channel,
return FALSE;
}
if (bytes == 0)
if (bytes == 0)
{
g_warning ("%s: wire_read: unexpected EOF", g_get_prgname ());
wire_error_val = TRUE;
......@@ -152,7 +155,7 @@ wire_read (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_write (GIOChannel *channel,
guint8 *buf,
gulong count)
......@@ -169,14 +172,17 @@ wire_write (GIOChannel *channel,
else
{
GIOError error;
guint bytes;
guint bytes;
while (count > 0)
{
do {
bytes = 0;
error = g_io_channel_write (channel, (char*) buf, count, &bytes);
} while (error == G_IO_ERROR_AGAIN);
do
{
bytes = 0;
error = g_io_channel_write (channel, (char*) buf, count, &bytes);
}
while ((error == G_IO_ERROR_AGAIN) ||
(error == G_IO_ERROR_UNKNOWN && errno == EINTR));
if (error != G_IO_ERROR_NONE)
{
......@@ -193,27 +199,28 @@ wire_write (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_flush (GIOChannel *channel)
{
if (wire_flush_func)
return (* wire_flush_func) (channel);
return FALSE;
}
int
wire_error ()
gboolean
wire_error (void)
{
return wire_error_val;
}
void
wire_clear_error ()
wire_clear_error (void)
{
wire_error_val = FALSE;
}
int
gboolean
wire_read_msg (GIOChannel *channel,
WireMessage *msg)
{
......@@ -234,7 +241,7 @@ wire_read_msg (GIOChannel *channel,
return !wire_error_val;
}
int
gboolean
wire_write_msg (GIOChannel *channel,
WireMessage *msg)
{
......@@ -267,7 +274,7 @@ wire_destroy (WireMessage *msg)
(* handler->destroy_func) (msg);
}
int
gboolean
wire_read_int32 (GIOChannel *channel,
guint32 *data,
gint count)
......@@ -287,7 +294,7 @@ wire_read_int32 (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_read_int16 (GIOChannel *channel,
guint16 *data,
gint count)
......@@ -307,7 +314,7 @@ wire_read_int16 (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_read_int8 (GIOChannel *channel,
guint8 *data,
gint count)
......@@ -315,13 +322,13 @@ wire_read_int8 (GIOChannel *channel,
return wire_read (channel, data, count);
}
int
gboolean
wire_read_double (GIOChannel *channel,
gdouble *data,
gint count)
{
char *str;
int i;
gchar *str;
gint i;
for (i = 0; i < count; i++)
{
......@@ -334,13 +341,13 @@ wire_read_double (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_read_string (GIOChannel *channel,
gchar **data,
gint count)
{
guint32 tmp;
int i;
gint i;
for (i = 0; i < count; i++)
{
......@@ -365,13 +372,13 @@ wire_read_string (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_write_int32 (GIOChannel *channel,
guint32 *data,
gint count)
{
guint32 tmp;
int i;
gint i;
if (count > 0)
{
......@@ -386,13 +393,13 @@ wire_write_int32 (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_write_int16 (GIOChannel *channel,
guint16 *data,
gint count)
{
guint16 tmp;
int i;
gint i;
if (count > 0)
{
......@@ -407,7 +414,7 @@ wire_write_int16 (GIOChannel *channel,
return TRUE;
}
int
gboolean
wire_write_int8 (GIOChannel *channel,
guint8 *data,
gint count)
......@@ -415,18 +422,19 @@ wire_write_int8 (GIOChannel *channel,
return wire_write (channel, data, count);