I took a quick look at the 2!:2 code and it's mostly ok in that the
file descriptors returned in the array are usable. Unfortunately using
it causes spurious errors crashes:
$ jconsole
a=: (2!:2) '/bin/ls -l'
a
28836 94660922311904 94660922312464
b =: mema 1024
|ill-formed number
...other J commands...
Program received signal SIGSEGV, Segmentation fault.
Note that "ill-formed number" error is incorrect. The parser has
gotten mixed up.
I tracked this down to the fdopen usage in 'jthostio'. If I move that
to after the fork call then the J system doesn't become unstable. This
patch basically:
------------------------------8<-------------------------
diff --git a/jsrc/xh.c b/jsrc/xh.c
index 912738b..93213e5 100644
--- a/jsrc/xh.c
+++ b/jsrc/xh.c
@@ -151,8 +151,6 @@ F1(jthostio){C*s;A z;F*pz;int fi[2],fo[2],r;int
fii[2],foi[2];
RZ(w=vs(w));
s=CAV(w); GAT(z,INT,3,1,0); pz=(F*)AV(z);
if((r=pipe(fii))==-1||pipe(foi)==-1){if(r!=-1)CL(fi); ASSERT(0,EVFACE);}
- if(!((pz[1]=fdopen(fi[0],"r"))&&(pz[2]=fdopen(fo[1],"w")))){
- if(pz[1])fclose(pz[1]); CL(fi);CL(fo);}
if(!add2(pz[1],pz[2],s)){fclose(pz[1]);fclose(pz[2]);
CL(fi);CL(fo);}
switch(r=fork()){
@@ -165,6 +163,8 @@ F1(jthostio){C*s;A z;F*pz;int fi[2],fo[2],r;int
fii[2],foi[2];
#endif
}close(fo[0]);close(fi[1]);
add2(NULL,NULL,NULL); pz[0]=(F)(intptr_t)r;
+ if(!((pz[1]=fdopen(fi[0],"r"))&&(pz[2]=fdopen(fo[1],"w")))){
+ if(pz[1])fclose(pz[1]); CL(fi);CL(fo);}
R z;
}
------------------------------8<-------------------------
Can anyone else duplicate this system instability?
1!:1 and 1!:11 still can't be used to read from these descriptors as
they attempt to seek the file. This fails as the file descriptors are
not seekable files, they're ends of a pipe. The return values of the
seek call aren't checked so no error is raised, the system gets
confused, and eventually a segfault occurs.
The seek occurs in 'jtrd', during the 'fsize' call:
https://github.com/jsoftware/jsource/blob/master/jsrc/xf.c#L83
'jtrd' gets called as part of the 1!:1 conjunction (the 'jtfjread' function):
https://github.com/jsoftware/jsource/blob/master/jsrc/xf.c#L124
Note there that it checks for the constant value 3 to indicate a read
from the non-seekable 'stdin' and that calls 'jtrdns' which doesn't do
an fsize or seek. Possible the code could detect for a non-seekable
descriptor and call 'jtrdns' but that's still not too useful for a
stream where you are reading and writing (eg. interacting with a
shell) since it would try to read the entire contents and block.
Maybe 1!:11 could be changed to detect and not seek (it calls fsize too):
https://github.com/jsoftware/jsource/blob/master/jsrc/xf.c#L188
it's possible though to use the FFI to use the descriptors:
a=: (2!:2) '/bin/ls -l'
a
28836 94660922311904 94660922312464
b=: mema 1024
b
94660922313024
'/lib/x86_64-linux-gnu/libc.so.6 fread > i *c i i x' cd
(<b);1;10;94660922311904
10
memr 94660922313024 0 8 2
total 16
--
http://bluishcoder.co.nz
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm