Re: [gtk-list] Re: gdk_io_* clarification



Okay folks, here's some code that will trigger the behaviour I see.  This
has only been tested on Solaris 7, YMMV on other platforms.

Explanation follows code.

--------------------------- cut here --------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <stdlib.h>
#include <gtk/gtk.h>

int fd;
FILE *f;
guint tag;

void dnotify(gpointer data)
{
  printf("dnotify called\n");
}

void ioready(gpointer data, gint source, GdkInputCondition condition)
{
  char buf[512];
  int n;

  if (condition & GDK_INPUT_READ) {
    n = read(fd, buf, 512);
    write(1, buf, n);
#ifndef WORKS
    gdk_input_remove(tag);
    gdk_input_add_full(fd, GDK_INPUT_READ, ioready, NULL,
                       dnotify);
#endif
    gdk_input_remove(tag);
    gdk_input_add_full(fd, GDK_INPUT_READ|GDK_INPUT_WRITE, ioready, NULL,
                       dnotify);
  }
  if (condition & GDK_INPUT_WRITE) {
    printf("Program can write now\n");
    exit(0);
  }
}

int main(int argc, char **argv)
{
  struct hostent *hp;
  struct sockaddr_in server;

  gtk_init(&argc, &argv);

  if (argc < 2) {
    fprintf(stderr, "Need server name as argument\n");
    return (114);
  }

  if ((hp = gethostbyname(argv[1])) == (struct hostent *)NULL)
    return (1);

  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    return (2);

  bzero((char *)&server, sizeof(server));
  server.sin_family = AF_INET;
  memcpy(&server.sin_addr, (char *)hp->h_addr, sizeof(u_long));
  server.sin_port = htons(119);

  if (connect(fd, (struct sockaddr *)&server, sizeof(server)) < 0)
    return (3);

  if (fcntl(fd, F_SETFL, O_NDELAY) == -1)
    return (4);

  if ((f = fdopen(fd, "w")) == (FILE *)NULL)
    return (5);

  tag = gdk_input_add_full(fd, GDK_INPUT_READ, ioready, NULL, dnotify);
  
  gtk_main();

  return (0);
}
--------------------------- cut here --------------------------------------

The problem here is repeated initialization of file descriptors inside a
handler.

Compile the above code and give it as the first and only argument the
name of an NNTP server (SMTP or POP would probably do too but you'd
need to change the hard-coded port number).  Compiled with -DWORKS I
get appropriate behaviour

miranda(130):~/projects/protclient% gcc -DWORKS `/opt/gnu/gtk-1.2/bin/gtk-config --cflags` -o ntest ntest.c `/opt/gnu/gtk-1.2/bin/gtk-config --libs` -R/opt/gnu/gtk-1.2/lib
miranda(0):~/projects/protclient% ./ntest miranda
200 miranda DNEWS Version 4.5i3, S0, posting OK
dnotify called
Program can write now

Without -DWORKS, it fails

miranda(0):~/projects/protclient% gcc `/opt/gnu/gtk-1.2/bin/gtk-config --cflags` -o ntest ntest.c `/opt/gnu/gtk-1.2/bin/gtk-config --libs` -R/opt/gnu/gtk-1.2/lib
miranda(0):~/projects/protclient% ./ntest miranda
200 miranda DNEWS Version 4.5i3, S0, posting OK 
dnotify called

[ just sits there]

	So that my protocol handlers don't have to reset the state of the
file descriptor when they have finished processing a command I put in an
extra step to turn off write notification and then the next command that
comes along sets the state as it requires.  This means that there are
usually *two* lots of gdk_input_remove() and gdk_input_add_full() per call
to my hanalder.  As you can see from the above, this is what is causing
the error.  I know this is rather obscure, but I think it's a bug in glib
or gdk.


Thanks.



--
James Macnicol
j-macnicol@adfa.edu.au



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]