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

Reply via email to