OS/2, eCS & ArcaOS - Technical > Programming
Networking: socket() returns positive `non-socket`
agena.info:
Hello,
I am having a big problem with socket programming in C:
Every time I open a socket with:
int sock = socket(AF_INET, SOCK_STREAM, 0);
and try to bind or connect later on I get an 38 error code, claiming that these functions have been called with a non-socket (`Socket operation on non-socket`).
The result returned by socket is always a positive integer, mostly starting from 3.
I even included a call to the undocumented addsockettolist() function after opening the socket, but to no avail.
What am I doing wrong ? I use ArcaOS 5.0.6 and Paul Smedley's GCC 4.4.6 and 8.3.0. I do not use any OS/2-specific flags like _EMX_TCPIP or TCPV40HDRS in the code (they wouldn't help anyway). Do I need to load any specific TCP/IP-related drivers during boot time other than the ones that are already included in CONFIG.SYS, or do I have to link against additional TCP/IP-specific libraries other than socket (-lsocket flag) ?
The C code that is run on ArcaOS to open, bind, connect, etc. is the very same as with Windows, Solaris, Linux, Mac OS X, where everyting works fine.
Any help would be appreciated.
Thank you,
Alex
Dave Yeo:
Post to the latest thread.
I'd patiently wait for a response from someone who knows this stuff. For many it is a long weekend.
Which headers are you using? Are you linking against libcx (-lcx). Also what cflags/ldflags are you using?
Steven Levine:
As Dave mentioned, we need know a bit more about your development setup and build options.
Since you are building with gcc, I'm going to assume for now that you are building with kLIBC and you are using the most recent versions of libn0.dll and libcx0.dll from the netlabs repos.
You should be using the OS/2 toolkit headers provided by the libc-devel package. They work better with gcc and kLIBC than the IBM supplied headers.
FWIW, addsockettolist and removesocketfromlist are documented and they are used by kLIBC. kLIBC needs them to implement fork().
Another FWIW, I have seen the ENOTSOCK failure mode when running git against large repositories on a busy system, but perhaps not for the same reason you are. In my case the failure is intermittent and retrying the git operation when the system is less busy typically avoids the failure.
Note that OS/2 has separate namepaces for sockets and file handles, unlike Linux. kLIBC emulates the Linux way to make porting apps simpler. This requires using kLIBC for all file and socket operations.
agena.info:
Hello,
thanks for your two replies. What I am trying to implement is a simple IPv4 library for a fork of the Lua programming language. What works fine in Windows, Solaris, Linux and Mac obviously does not work with ArcaOS:
1) Have one C function that opens a socket and returns its descriptor, a positive integer, to the Lua environment.
2) Have additional, separate C functions that take the socket descriptor from 1) and that bind, connect, etc.
I guess that as soon as the scope of C function 1) in ArcaOS is left and the interpreter returns to the Lua environment, any info on the socket descriptor is lost and the socket is automatically closed so that all the other functions 2) reject it ?
It only works in ArcaOS if I combine a call to socket() and bind() in one and the same C function, see below, but this does not work for me.
Here are the essential code snippets, compiled with GCC 8.3.0 as follows:
gcc -o agena.exe -s agena.o -L. -lm -lagena -lm -lmapm -lz -lreadline -lncurses -ltinfo -lhistory -liconv -lexpat -lmpfr -lgmp -lg2 -lgd -lpcre2-posix -lpcre2-8 -lfi_lib -lsocket
#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h> /* to be put before sys/socket.h */
#include <stddef.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h> /* must come before arpa/inet.h */
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <unistd.h>
... further Lua-specific includes ...
The following function, successfully returns a positive socket descriptor, mostly starting from 3:
static int net_openos2 (lua_State *L) {
int sock;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
errornosock(L, "socket could not be created", "net.openos2"); /* bails out */
}
lua_pushinteger(L, sock);
return 1;
}
The next function net_bindos2, however, rejects the socket descriptor returned by net_openos2, and quits with a `Socket operation on non-socket` error:
static int net_bindos2 (lua_State *L) {
struct in_addr addr;
struct sockaddr_in server;
int port = 1234;
const char *address = "127.0.0.1";
int sock = luaL_checkinteger(L, 1);
if (sock < 2) {
errornosock(L, "socket is invalid", "net.bindos2"); /* bails out */
}
/* initiate binding */
tools_memset(&server, 0, sizeof(struct sockaddr_in));
if ((inet_aton(address, &addr)) != 0) { /* valid address ? */
tools_memcpy((char *)&server.sin_addr, &addr, sizeof(addr));
} else {
errornosock(L, "failure", "net.bindos2"); /* bails out */
}
server.sin_family = AF_INET;
server.sin_port = htons(port);
/* do it */
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
agn_neterror(L); /* bails out */
}
lua_pushstring(L, inet_ntoa(server.sin_addr));
return 1;
}
This one works fine in ArcaOS:
static int net_openandbind (lua_State *L) {
int sock;
struct in_addr addr;
struct sockaddr_in server;
int port = 1234;
const char *address = "127.0.0.1";
/* open socket */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
errornosock(L, "socket could not be created", "net.openandbind"); /* bails out */
}
/* initiate binding */
tools_memset(&server, 0, sizeof(struct sockaddr_in));
if ((inet_aton(address, &addr)) != 0) { /* valid address ? */
tools_memcpy((char *)&server.sin_addr, &addr, sizeof(addr));
} else {
errornosock(L, "failure", "net.bindos2"); /* bails out */
}
server.sin_family = AF_INET;
server.sin_port = htons(port);
/* do it */
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
agn_neterror(L); /* bails out */
}
lua_pushinteger(L, sock);
return 1;
}
Dave Yeo:
Hi, not much of a programmer so I'll let others comment on the code.
For your linking line, I'd drop the -lsocket, it's not needed with current libc. Add -lcx (libc extensions) and also use -Zomf, probably before the -L.
-Zomf will convert the object files to native OMF and use the system linker rather then the ancient ld. You may have to install watcom-wlink-hll using yum and set things up to use wl.exe as the linker. Run emxomfld with no parameters to see the needed environment variables. -Zomf is also required to use debuggers, of which only native ones work.
Once working -Zhigh-mem is a good LDFLAG to use memory in the high arena (above 1GB). -Zmap is handy to build a map file for debugging purposes.
Is there a reason not to start out using the yum installed GCC 9.2.0? Includes, libs etc will just work and after you have it working, you can rebuild with the older GCC's if you choose.
Navigation
[0] Message Index
[#] Next page
Go to full version