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).
_______________________________________________
Bug-gnustep mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-gnustep