bug-gnustep
[Top][All Lists]
Advanced

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

Re: NSPortMessage doesn't work with NSSocketPort


From: Richard Frith-Macdonald
Subject: Re: NSPortMessage doesn't work with NSSocketPort
Date: Mon, 31 Dec 2007 21:12:02 +0000


On 30 Dec 2007, at 14:36, Christian Stieber wrote:

As the subject says :-)

"It all started" with my app not working (what a surprise), and no
matter what, I couldn't find anything wrong with it. Originally I
thought is was because I'm using Debian, and that installed two
versions of libobjc that the linker warned me could conflict, so I
downloaded the current svn version just yesterday, eventually got
it to compile, and despite the linker warning being gone now it
still doesn't work.

Now, to the "it". I'm sending a NSPortMessage, containing one NSData,
via an NSSocketPort. It never arrives, or causes the receiver to spit
out messages about invalid data. Took me a while to figure out how
to connect two socket ports, but that part seemed to work.

Since I had the svn version anyway, I decided to waste some time with
this chaotic code and try to understand what it's doing. From the
looks of it, you are sending a header item followed by data items, so
I added a few printf() to see what's actually received. Turned out,
apparently, it never gets the last data item. If I send 3 NSData, I
receive 2 GSP_DATA, and then it probably waits for the 3rd to arrive.

Looking at what appears to be the sending code, I found this in
NSSocketPort.m:2384

      /*
       * Now insert item header information as required.
* Pack as many items into the initial data object as possible, up to
       * a maximum of NETBLOCK bytes.  This is to try to get a single,
       * efficient write operation if possible.
       */
      for (i = 1; i < c; i++)
        {
          id    o = [components objectAtIndex: i];


I'm not quite sure whether I'm seeing this right, but it appears that
this could be the source of the problem: a few lines earlier, an additional
NSData it is inserted into the components array at index 0, so you
correctly start at index 1 here. Except that "c" is the item count before
that new item is inserted, so this loop never hits the last item.
Unfortunately, the item count in the header includes the last one...
so the message is never received completely, and I can't just work
around this problem by adding a dummy item at the end (this does look
like a possible workaround, though --- adding a category for the final
send after that loop, and reducing the item count in the header by 1.
Still have to find out whether I can call the original implementation
of the method, though).

As a quick test, I replaced the "i < c" with "i < c+1" (which isn't a
fix, of course...) --- and what do you know, I suddenly receive my
message. Sending two messages (the app is still in an early stage...)
in a row seems to work as well, so apparently there are no sync
probblems introduced by the test hack.

So *maybe* you'll just need a flag to remember whether you've put that
additional item into the array, and add that to the c in the loop.
Which won't help me; apparently the debian version is (like always
with Debian) already way behind your svn version... and I don't really
have the time to wait 3 years for Debian to pick up a fix :-)

Christian

OK ... the problem is with sending a port message without having reserved space for the header in its first data item ... and obviously doesn't show up in anyone elses apps because normally the first data item in a port message has the space reserve (but in your case it hasn't). The simple fix for the bug is to set the count (c) immediately before entering the loop.

The NSPortMessage class really isn't much good for use directly by most apps ... it's normally only used by NSConnection, and there is realistically no advantage to be gained by apps using the low-level NSPortMessage class directly rather than using the higher level NSConnection. That is to say, the class is exposed only because Apple decided to expose it in MacOS-X, not because it's actually generally useful. The one place you would really expect to use it would be implementing distributed objects over new network protocols ... pretty advanced stuff.

Bashing follows.

GNUstep is getting seriously annoying :-( Maybe the code really is as
bugged as it appears --- after all, sending data over a socket really
isn't a common usecase, right;

Well, NSPortMessage and NSSocketPort are NOT for sending data over a socket. They are for sending port messages over a socket port (ie a higher level protocol, part of the distributed objects system rather than raw data over a socket), and that means that you can't use them to send to anything other than a GNUstep application (because the app at the other end won't understand the protocol). The NSStream and NSFileHandle APIs are designed for sending raw data over sockets (or to files etc) and are normally what you would use to talk to non- GNUstep apps (except the common case of HTTP/HTTPS/FTP for which NSURL and related classes provide a high level API).

this isn't the first problem I run into,
it's just the first I tried to look into while trying to figure out the
best way to work around it, or the documentation is even more terrible
than I thought so far since it gives no indication how to use this
properly... especially in this case, since the Cocoa NSSocketPort has a
completely different API, so the generally far better Apple docs don't
work.

True, but the documentation there is, is pretty clear that the NSPort stuff is for distributed objects, and there's fairly good documentation on how to use distributed objects (eg in the manual in the base distribution). You found a bug because it's very unusual for anyone to try playing with the internals of the distributed objects system to do something other than distributed objects. Most likely what you actually want is NSStream or NSFileHandle (if you are wanting to send/receive raw data) or NSConnection (to send or receive messages with objects as parameters).





reply via email to

[Prev in Thread] Current Thread [Next in Thread]