Re: [9fans] syscall silently kill processes

2022-06-28 Thread andrey100100100
В Вт, 28/06/2022 в 15:28 +, adr пишет:
> Andrey, if you want to use different note handlers per process (with
> a big
> number of processes) using libthread, this may be helpful.
> 
> The idea is this:
> 
> An array of handlers for all processes which can be changed by all
> processes.
> When a note is received by a process, this array takes priority.
> 
> An array of pointers to structures of the type
> 
> struct Onnote
> {
>     int pid;
>     int (*fn[NFN])(void*, char*);
> };
> 
> initially of size PPCHUNK (I set it to 100, experiment with that),
> but it can grow if necessary (but not shrink, I think this would
> be overkilling).
> 
> These structures are allocated the first time a process record a
> handler and freed when the process exits (or by calling
> threadcancelnotes(), note that this function can free other
> processes'
> function handlers, maybe should be better to make some restrictions)
> 
> The use of "in" in threadnotify(int (*f)(void*, char*), int in) is:
> 
> in > 0 : set the handler for the calling process.
> in == 0 : clear the handler for the calling process.
> in == -1 : clear the handler for all processes (except those who has
>     registered it already for themselves).
> in < -1 : set the handler for all processes.
> 
> There is no use of threadnotify with "in < 0" in /sys/src, so nothing
> is broken.
> 
> As you are using 9front and they are serving their sources with
> 9p, here is a diff to their sources. I haven't compiled it in
> 9front, though. Note that if you want to compile the system with
> this changes, you have to eliminate the copy of note.c at
> /sys/src/cmd/execnet (it seems that note.c was added afterwards as
> I thought).
> 
> I haven't test it too much, this has been more like a time-destroyer
> pastime.
> 
> adr
> --- /tmp/main.c
> +++ /sys/src/libthread/main.c
> @@ -28,6 +28,10 @@
>     _qlockinit(_threadrendezvous);
>     _sysfatal = _threadsysfatal;
>     __assert = _threadassert;
> +   onnote = mallocz(PPCHUNK*sizeof(uintptr), 1);
> +   if(!onnote)
> +   sysfatal("Malloc of size %d failed: %r",
> PPCHUNK*sizeof(uintptr));
> +   onnotesize = PPCHUNK;
>     notify(_threadnote);
>     if(mainstacksize == 0)
>     mainstacksize = 8*1024;
> --- /tmp/note.c
> +++ /sys/src/libthread/note.c
> @@ -5,9 +5,9 @@
> 
>   int   _threadnopasser;
> 
> -#define    NFN 33
>   #define   ERRLEN  48
>   typedef struct Note Note;
> +
>   struct Note
>   {
>     Lock    inuse;
> @@ -17,62 +17,155 @@
> 
>   static Note   notes[128];
>   static Note   *enotes = notes+nelem(notes);
> -static int (*onnote[NFN])(void*, char*);
> -static int onnotepid[NFN];
> +Onnote **onnote;
> +int onnotesize;
> +static int (*onnoteall[NFN])(void*, char*);
>   static Lock   onnotelock;
> 
>   int
>   threadnotify(int (*f)(void*, char*), int in)
>   {
> -   int i, topid;
> -   int (*from)(void*, char*), (*to)(void*, char*);
> +   int i, j;
> 
> -   if(in){
> -   from = nil;
> -   to = f;
> -   topid = _threadgetproc()->pid;
> -   }else{
> -   from = f;
> -   to = nil;
> -   topid = 0;
> -   }
>     lock();
> -   for(i=0; i -   if(onnote[i]==from){
> -   onnote[i] = to;
> -   onnotepid[i] = topid;
> +
> +   /* add note for all processes */
> +   if(in < -1){
> +   for(i=0; i +   if(onnoteall[i] == f){
> +   unlock();
> +   return 1;
> +   }
> +   for(i=0; i +   if(onnoteall[i] == nil){
> +   onnoteall[i] = f;
> +   break;
> +   }
> +   unlock();
> +   return i +   }
> +
> +   /* remove note for all processes */
> +   if(in == -1){
> +   for(i=0; i +   if(onnoteall[i] == f){
> +   onnoteall[i] = nil;
> +   break;
> +   }
> +   unlock();
> +   return i +   }
> +
> +   /* remove note for current process */
> +   if(!in){
> +   for(i=0; i +   if(onnote[i]!=nil && onnote[i]-
> >pid==_threadgetproc()->pid){
> +   for(j=0; j +   if(onnote[i]->fn[j] == f){
> +   onnote[i]->fn[j] = 0;
> +   break;
> +   }
> +   }
> +   unlock();
> +   return j +   }
> +   }
> +   unlock();
> +   

Re: [9fans] syscall silently kill processes

2022-06-21 Thread andrey100100100
В Вт, 21/06/2022 в 11:26 +, adr пишет:
> On Tue, 21 Jun 2022, andrey100100...@gmail.com wrote:
> > ? ??, 20/06/2022 ? 15:29 -0700, Skip Tavakkolian ?:
> > > It's cleaner to use channels with separate io and timer threads
> > > that
> > > do their syscalls via ioproc; this one doesn't require any
> > > changes to
> > > libthread:
> > > 
> > > https://gist.github.com/9nut/aaa9b9b6a22d69996b75ccdc6e615c61
> > 
> > Thanks for the work you've done!
> > Yes, I have considered this possibility.
> > But it was precisely this kind of code bloat that I wanted to
> > avoid.
> 
> It looks like code bloat, but it really isn't. It is doing the job
> with the tools of the api according to the paradigm designed in
> libthread. That's why the word "cleaner" is completely correct.

And one more problem:

cpu% 6.out -a 'udp!52.43.121.77!10011' -n 250 -t 7 | grep time | wc -l
6.out 50974: warning: process exceeds 100 file descriptors
6.out 51053: warning: process exceeds 200 file descriptors
6.out 51238: warning: process exceeds 300 file descriptors
6.out 51314: warning: process exceeds 400 file descriptors
6.out 51342: warning: process exceeds 500 file descriptors
6.out 51414: warning: process exceeds 600 file descriptors
6.out 51158: warning: process exceeds 700 file descriptors
250


cpu% ps | grep 6.out | wc -l
751


Сonsumes three times more resources than it should.

> 
> I think note.c was added to resolve some particual case, and for
> the state of note.c, I don't think it has been used too much.
> 
> For example, let's remove note.c. You could obtain the same result
> in your example (all processes using the same handler) using atnotify
> because the notes are registered to the children when proccreate
> uses rfork:
> 
> void
> threadmain(int argc, char *argv[])
> {
>     atnotify(handler_alarm, 1);
> 
> ./5.out | grep end | wc -l
>     80
> 
> If you have to use a different handler for each processes you can't
> use atnotify because of RFMEM, but you can use the syscalls notify
> and noted:
> 
> #include  
> #include  
> #include 
> 
> static void
> handler_alarm(void *, char *msg)
> {
>     if(strstr(msg, "alarm")){
>     print("yes");
>     noted(NCONT);
>     return; /* just in case */
>     }
>     noted(NDFLT);
> }
> 
> static void
> proc_udp(void *)
> {
>     char resp[512];
>     char req[] = "request";
>     int fd;
>     notify(handler_alarm);
>     if((fd = dial("udp!185.157.221.201!5678", nil, nil, nil)) >=
> 0){
>     if(write(fd, req, strlen(req)) == strlen(req)){
>     fprint(1, "start\n");
>     alarm(2000);
>     read(fd, resp, sizeof(resp));
>     alarm(0);
>     fprint(1, "end\n");
>     }
>     close(fd);
>     }
>     threadexits(nil);
> }
> 
> int mainstacksize = 5242880;
> 
> void
> threadmain(int argc, char *argv[])
> {
>     for(int i = 0; i < 80; i++)
>     proccreate(proc_udp, nil, 10240);
>     sleep(5000);
>     threadexitsall(nil);
>   }
> 
> ./5.out | grep end | wc -l
>     80
> 
> Threadnotify is trying to do an atnotify that works with RFMEM,
> but to do that onnote should be allocated to grow or shrink (or
> have a size thinking in the maximum number of processes the program
> could spawn, not the number of handlers a process could register
> as in atnotify), instead of pointers to handlers, it should be an
> array of pointers to arrays of handlers allocated by each process.
> 
> Now again, does the notes mechanism actually fit in libthread? If
> it does it should be fixed, if not removed.
> 


Regards,
Andrej


--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-M813e896da7e1be8ab8338198
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-21 Thread andrey100100100
В Вт, 21/06/2022 в 11:26 +, adr пишет:
> On Tue, 21 Jun 2022, andrey100100...@gmail.com wrote:
> > ? ??, 20/06/2022 ? 15:29 -0700, Skip Tavakkolian ?:
> > > It's cleaner to use channels with separate io and timer threads
> > > that
> > > do their syscalls via ioproc; this one doesn't require any
> > > changes to
> > > libthread:
> > > 
> > > https://gist.github.com/9nut/aaa9b9b6a22d69996b75ccdc6e615c61
> > 
> > Thanks for the work you've done!
> > Yes, I have considered this possibility.
> > But it was precisely this kind of code bloat that I wanted to
> > avoid.
> 
> It looks like code bloat, but it really isn't. It is doing the job
> with the tools of the api according to the paradigm designed in
> libthread. That's why the word "cleaner" is completely correct.

Yes, ready to agree, this solution is more independent of low-level
features and more obvious.

But, i would like more compact code.

I wonder how threadnotify() in plan9port will behave...

> 
> I think note.c was added to resolve some particual case, and for
> the state of note.c, I don't think it has been used too much.
> 
> For example, let's remove note.c. You could obtain the same result
> in your example (all processes using the same handler) using atnotify
> because the notes are registered to the children when proccreate
> uses rfork:
> 
> void
> threadmain(int argc, char *argv[])
> {
>     atnotify(handler_alarm, 1);
> 
> ./5.out | grep end | wc -l
>     80
> 
> If you have to use a different handler for each processes you can't
> use atnotify because of RFMEM, but you can use the syscalls notify
> and noted:
> 
> #include  
> #include  
> #include 
> 
> static void
> handler_alarm(void *, char *msg)
> {
>     if(strstr(msg, "alarm")){
>     print("yes");
>     noted(NCONT);
>     return; /* just in case */
>     }
>     noted(NDFLT);
> }
> 
> static void
> proc_udp(void *)
> {
>     char resp[512];
>     char req[] = "request";
>     int fd;
>     notify(handler_alarm);
>     if((fd = dial("udp!185.157.221.201!5678", nil, nil, nil)) >=
> 0){
>     if(write(fd, req, strlen(req)) == strlen(req)){
>     fprint(1, "start\n");
>     alarm(2000);
>     read(fd, resp, sizeof(resp));
>     alarm(0);
>     fprint(1, "end\n");
>     }
>     close(fd);
>     }
>     threadexits(nil);
> }
> 
> int mainstacksize = 5242880;
> 
> void
> threadmain(int argc, char *argv[])
> {
>     for(int i = 0; i < 80; i++)
>     proccreate(proc_udp, nil, 10240);
>     sleep(5000);
>     threadexitsall(nil);
>   }
> 
> ./5.out | grep end | wc -l
>     80
> 
> Threadnotify is trying to do an atnotify that works with RFMEM,
> but to do that onnote should be allocated to grow or shrink (or
> have a size thinking in the maximum number of processes the program
> could spawn, not the number of handlers a process could register
> as in atnotify), instead of pointers to handlers, it should be an
> array of pointers to arrays of handlers allocated by each process.
> 
> Now again, does the notes mechanism actually fit in libthread? If
> it does it should be fixed, if not removed.


I vote for the fix.
Perhaps the notification is being used somewhere or by someone.


> 
> adr.
> 

Regards,
Andrej

--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-Mf8c7cfd50b4091a520d792e5
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-21 Thread andrey100100100
В Пн, 20/06/2022 в 15:29 -0700, Skip Tavakkolian пишет:
> It's cleaner to use channels with separate io and timer threads that
> do their syscalls via ioproc; this one doesn't require any changes to
> libthread:
> 
> https://gist.github.com/9nut/aaa9b9b6a22d69996b75ccdc6e615c61

Thanks for the work you've done!
Yes, I have considered this possibility.
But it was precisely this kind of code bloat that I wanted to avoid.

And yet, the libthread needs fixing. What adr suggested, at first
glance, is acceptable.
And it turns out that we are trying to get around the problems of the
libthread using the libthread...
By not fixing the libthread, we reduce the number of use cases for it,
which is bad.


PS. Philosophical question: should someone monitor the process or
should the process serve itself?


> 
> 
> On Mon, Jun 20, 2022 at 8:57 AM  wrote:
> > 
> > В Пн, 20/06/2022 в 05:59 +, adr пишет:
> > > On Mon, 20 Jun 2022, adr wrote:
> > > > But I have something in mind for a case like
> > > > this, when all the processes are going to use the same handler
> > > > (that's why I was asking). Let me play with it a litle before I
> > > > share it.
> > > 
> > > Ok, the idea is this: If in is bigger than zero in
> > > threadnotify(int (*f)(void*, char*), int in), the handler is
> > > register
> > > for the calling process. If in is 0, then the handler is cleared
> > > for the calling process. If in is -1, the handler is register for
> > > all processes and if in is less than -1, it is cleared for all
> > > processes (expect for those who have already registered it for
> > > themselves).
> > > 
> > > Now back to your example, as all the processes are going to use
> > > the
> > > same handler,
> > > you just have to register it once in threadmain:
> > > 
> > > #include 
> > > #include 
> > > #include 
> > > 
> > > static int
> > > handler_alarm(void *, char *msg)
> > > {
> > >     if(strstr(msg, "alarm"))
> > >     return 1;
> > >     return 0;
> > > }
> > > 
> > > static void
> > > proc_udp(void *)
> > > {
> > >     char resp[512];
> > >     char req[] = "request";
> > >     int fd;
> > >     if((fd = dial("udp!185.157.221.201!5678", nil, nil, nil))
> > > 0){
> > >     if(write(fd, req, strlen(req)) == strlen(req)){
> > >     fprint(1, "start\n");
> > >     alarm(2000);
> > >     read(fd, resp, sizeof(resp));
> > >     alarm(0);
> > >     fprint(1, "end\n");
> > >     }
> > >     close(fd);
> > >     }
> > >     threadexits(nil);
> > > }
> > > 
> > > int mainstacksize = 5242880;
> > > 
> > > void
> > > threadmain(int argc, char *argv[])
> > > {
> > >     threadnotify(handler_alarm, -1);
> > >     for(int i = 0; i < 80; i++)
> > >     proccreate(proc_udp, nil, 10240);
> > >     sleep(5000);
> > >     threadexitsall(nil);
> > > }
> > > Now,
> > > ; ./5.out | grep end | wc -l
> > >   80
> > > 
> > > Are you happy Andrej?
> > 
> > 
> > Yes. Thank you very much! It's working!
> > 
> > How convenient it is to use - more experiments are needed.
> > 
> > 
> > > 
> > > adr.
> > > 
> > > /sys/src/libthread/sched.c:
> > > [...]
> > >     if(t == nil){
> > >     _threaddebug(DBGSCHED, "all threads gone;
> > > exiting");
> > >     cancelnotes(p->pid);
> > >     _schedexit(p);
> > >     }
> > > [...]
> > > /sys/src/libthread/note.c
> > > [...]
> > > int
> > > threadnotify(int (*f)(void*, char*), int in)
> > > {
> > >     int i, frompid, topid;
> > >     int (*from)(void*, char*), (*to)(void*, char*);
> > > 
> > >     if(in && in>-2){
> > >     from = nil;
> > >     frompid = 0;
> > >     to = f;
> > >     topid = (in == -1)? -1 : _threadgetproc()->pid;
> > >     lock();
> > >     for(i=0; i > >     if(onnote[i]==to && onnotepid[i]==topid){
> > >     unlock();
> > >     return i > >     }
> > >     unlock();
> > >     }else{
> > >     from = f;
> > >     frompid = (in < -1)? -1 : _threadgetproc()->pid;
> > >     to = nil;
> > >     topid = 0;
> > >     }
> > >     lock();
> > >     for(i=0; i > >     if(onnote[i]==from && onnotepid[i]==frompid){
> > >     onnote[i] = to;
> > >     onnotepid[i] = topid;
> > >     break;
> > >     }
> > >     unlock();
> > >     return i > > }
> > > 
> > > void
> > > cancelnotes(int pid)
> > > {
> > >     int i;
> > > 
> > >     lock();
> > >     for(i=0; i > >     if(onnotepid[i] == pid){
> > >     onnote[i] = nil;
> > >  

Re: [9fans] syscall silently kill processes

2022-06-20 Thread andrey100100100
В Пн, 20/06/2022 в 05:59 +, adr пишет:
> On Mon, 20 Jun 2022, adr wrote:
> > But I have something in mind for a case like
> > this, when all the processes are going to use the same handler
> > (that's why I was asking). Let me play with it a litle before I
> > share it.
> 
> Ok, the idea is this: If in is bigger than zero in
> threadnotify(int (*f)(void*, char*), int in), the handler is register
> for the calling process. If in is 0, then the handler is cleared
> for the calling process. If in is -1, the handler is register for
> all processes and if in is less than -1, it is cleared for all
> processes (expect for those who have already registered it for
> themselves).
> 
> Now back to your example, as all the processes are going to use the
> same handler,
> you just have to register it once in threadmain:
> 
> #include  
> #include  
> #include 
> 
> static int
> handler_alarm(void *, char *msg)
> {
>     if(strstr(msg, "alarm"))
>     return 1;
>     return 0;
> }
> 
> static void
> proc_udp(void *)
> {
>     char resp[512];
>     char req[] = "request";
>     int fd;
>     if((fd = dial("udp!185.157.221.201!5678", nil, nil, nil)) >=
> 0){
>     if(write(fd, req, strlen(req)) == strlen(req)){
>     fprint(1, "start\n");
>     alarm(2000);
>     read(fd, resp, sizeof(resp));
>     alarm(0);
>     fprint(1, "end\n");
>     }
>     close(fd);
>     }
>     threadexits(nil);
> }
> 
> int mainstacksize = 5242880;
> 
> void
> threadmain(int argc, char *argv[])
> {
>     threadnotify(handler_alarm, -1);
>     for(int i = 0; i < 80; i++)
>     proccreate(proc_udp, nil, 10240);
>     sleep(5000);
>     threadexitsall(nil);
> }
> Now,
> ; ./5.out | grep end | wc -l
>   80
> 
> Are you happy Andrej?


Yes. Thank you very much! It's working!

How convenient it is to use - more experiments are needed.


> 
> adr.
> 
> /sys/src/libthread/sched.c: 
> [...]
>     if(t == nil){
>     _threaddebug(DBGSCHED, "all threads gone;
> exiting");
>     cancelnotes(p->pid);
>     _schedexit(p);
>     } 
> [...] 
> /sys/src/libthread/note.c 
> [...] 
> int 
> threadnotify(int (*f)(void*, char*), int in) 
> {
>     int i, frompid, topid;
>     int (*from)(void*, char*), (*to)(void*, char*);
> 
>     if(in && in>-2){
>     from = nil;
>     frompid = 0;
>     to = f;
>     topid = (in == -1)? -1 : _threadgetproc()->pid;
>     lock();
>     for(i=0; i     if(onnote[i]==to && onnotepid[i]==topid){
>     unlock();
>     return i     }
>     unlock();
>     }else{
>     from = f;
>     frompid = (in < -1)? -1 : _threadgetproc()->pid;
>     to = nil;
>     topid = 0;
>     }
>     lock();
>     for(i=0; i     if(onnote[i]==from && onnotepid[i]==frompid){
>     onnote[i] = to;
>     onnotepid[i] = topid;
>     break;
>     }
>     unlock();
>     return i }
> 
> void
> cancelnotes(int pid)
> {
>     int i;
> 
>     lock();
>     for(i=0; i     if(onnotepid[i] == pid){
>     onnote[i] = nil;
>     onnotepid[i] = 0;
>     }
>     unlock();
>     return;
> }
> 
> static void
> delayednotes(Proc *p, void *v)
> {
>     int i;
>     Note *n;
>     int (*fn)(void*, char*);
> 
>     if(!p->pending)
>     return;
> 
>     p->pending = 0;
>     for(n=notes; n     if(n->proc == p){
>     for(i=0; i     if((onnotepid[i]!=p->pid &&
> onnotepid[i]!=-1) || (fn = onnote[i])==nil)
>     continue;
>     if((*fn)(v, n->s))
>     break;
> [...]
> /sys/include/thread.h 
> [...] 
> void cancelnotes(int pid); 
> [...] 
> 

Regards,
Andrej

--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-M3802ed594c69b660a4210973
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-19 Thread andrey100100100
В Пн, 20/06/2022 в 04:41 +, adr пишет:
> On Mon, 20 Jun 2022, andrey100100...@gmail.com wrote:
> > The note 'alarm' is needed to interrupt the system call on timeout
> > since system calls to lan 9 can be of a network nature, a notes is
> > indispensable.
> > A great example of this is the read() system call on a udp-
> > connection.
> > How else can this system call be interrupted?
> 
> Start two processes, one which just make the call, another as a
> timer to kill it.

Yes, I had such an idea, but in the thread library, process IDs
increase monotonically, which is bad (due to IDs overflow) for long-
lived and actively spawning programs.

On the other hand, with process IDs, as in the kernel (reuse of IDs),
it is also required to receive group notes in case of an unexpected
termination of the child.

I.e. the problem is in identifying the processes to kill.

>  But I have something in mind for a case like
> this, when all the processes are going to use the same handler
> (that's why I was asking).

It would be great if could undo handler (delete from onnote or
something similar).

>  Let me play with it a litle before I
> share it.
> 
> adr.
> 


Regards,
Andrej

--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-M6bc161e383ef6a388d7c5b0a
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-19 Thread andrey100100100
В Пн, 20/06/2022 в 00:22 +0300, andrey100100...@gmail.com пишет:
> В Вс, 19/06/2022 в 16:41 +, adr пишет:
> > On Sun, 19 Jun 2022, andrey100100...@gmail.com wrote:
> > > Yes, you were absolutely right, the thread library needs some
> > > work.
> > > 
> > > It is impossible to use multiple processes with notes, due to the
> > > exhaustion of the NFN limit.
> > 
> > Andrej, what are you going to do with alarm in the real thing?
> 
> The note 'alarm' is needed to interrupt the system call on timeout
> since system calls to lan 9 can be of a network nature, a notes is
> indispensable.
> A great example of this is the read() system call on a udp-
> connection.
> How else can this system call be interrupted?
> 
> 
> 
> > You could use threads (cooperative round-ribbon multitasking) using
> > some data log to register their state and use a "master" thread to
> > control them (kill them, change some data structure, etc).
> > 
> > You can use rfork, locks, pipes, etc and forget about libthread.


Channels are a good abstraction for exchanging data between processes.
Even if not to use the libthread, I would have to (probably) write it.
But yeah, maybe it's easier to do without it.

> > 
> > You could experiment with the topology of the nodes, for example
> > instead of a big star you can simplify things a lot using chains
> > of nodes where the last node sends the chain data to the analyzer
> > (you were talking about polling sensors):
> > 
> > aNode1 --> aNode2 --> aNode3 --> ... --> aNoden -->
> >    
> >   
> >   > --- > Anz
> > bNode1 --> bNode2 --> bNode3 --> ... --> bNoden -->
> > 
> > Imagine that n=100. Each node only has to make a connection with
> > 2 nodes (the first of the chain just one), adding data to the
> > received one and send it to the next. Anz only has to make a
> > connection with the last nodes of the chains, two in this case,
> > and process the data received. Of course you have to play with your
> > numbers, the acceptable delay, etc.
> > 
> > I'm pretty sure people here could point you to some examples using
> > plan9, and note that you could use raspberry pi zeros as nodes.
> > 
> > Have fun.
> > 

Regards,
Andrej


--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-M06156a275c41ac100d18311b
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-19 Thread andrey100100100
В Вс, 19/06/2022 в 16:41 +, adr пишет:
> On Sun, 19 Jun 2022, andrey100100...@gmail.com wrote:
> > Yes, you were absolutely right, the thread library needs some work.
> > 
> > It is impossible to use multiple processes with notes, due to the
> > exhaustion of the NFN limit.
> 
> Andrej, what are you going to do with alarm in the real thing?

The note 'alarm' is needed to interrupt the system call on timeout
since system calls to lan 9 can be of a network nature, a notes is
indispensable.
A great example of this is the read() system call on a udp-connection.
How else can this system call be interrupted?



> You could use threads (cooperative round-ribbon multitasking) using
> some data log to register their state and use a "master" thread to
> control them (kill them, change some data structure, etc).
> 
> You can use rfork, locks, pipes, etc and forget about libthread.
> 
> You could experiment with the topology of the nodes, for example
> instead of a big star you can simplify things a lot using chains
> of nodes where the last node sends the chain data to the analyzer
> (you were talking about polling sensors):
> 
> aNode1 --> aNode2 --> aNode3 --> ... --> aNoden -->
>  
>   > --- > Anz
> bNode1 --> bNode2 --> bNode3 --> ... --> bNoden -->
> 
> Imagine that n=100. Each node only has to make a connection with
> 2 nodes (the first of the chain just one), adding data to the
> received one and send it to the next. Anz only has to make a
> connection with the last nodes of the chains, two in this case,
> and process the data received. Of course you have to play with your
> numbers, the acceptable delay, etc.
> 
> I'm pretty sure people here could point you to some examples using
> plan9, and note that you could use raspberry pi zeros as nodes.
> 
> Have fun.
> 
> --
> 9fans: 9fans
> Permalink:
> https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-Md1b869bf61deccadf9733908
> Delivery options:
> https://9fans.topicbox.com/groups/9fans/subscription

--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-M24ba5edacde926075a431016
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-19 Thread andrey100100100
В Вс, 19/06/2022 в 10:32 +, adr пишет:
> On Sun, 19 Jun 2022, andrey100100...@gmail.com wrote:
> > No way. All processes must run simultaneously.
> > NFN limit cannot be bypassed.
> 
> Yeah, that's why I said it was silly:
> > > > The solution is obvious, cancel the process' handlers before it
> > > > exits so we don't run out of space.
> > > 
> > > This was really silly...
> 
> The changes I'm testing are not for evading the limit, but for
> making the handler managment more efficient and specially to avoid
> the case when a process could remove another process' handler from
> onnote[].
> 

Yes, you were absolutely right, the thread library needs some work.

It is impossible to use multiple processes with notes, due to the
exhaustion of the NFN limit.

as example:


-
#include 
#include 
#include 

static int
handler_alarm(void *, char *msg)
{
if(strstr(msg, "alarm")){
return 1;
}

return 0;
}

static void
proc_func(void *c)
{
Channel *chan = c;

int fd;
char req[] = "request";
char resp[512], *r = nil;

if(threadnotify(handler_alarm, 1) == 0){
fprint(1, "handler not registred\n");
}

alarm(2000);
if((fd = dial("udp!185.157.221.201!5678", nil, nil, nil)) >=
0){
alarm(0);
alarm(2000);
if(write(fd, req, strlen(req)) == strlen(req)){
alarm(0);
alarm(2000);
if(read(fd, resp, sizeof(resp)) > 0){
alarm(0);
if((r = malloc(sizeof(resp))) == nil){
sysfatal("malloc error: %r");
}
memmove(r, resp, sizeof(resp));
}
}
close(fd);
}

alarm(0);
send(chan, r);
threadexits(nil);
}

int mainstacksize = 5242880;

void
threadmain(int argc, char *argv[])
{
Channel *chan = nil;
char *data = nil;
int nproc = 0;

ARGBEGIN{
case 'n':
nproc = atoi(EARGF(threadexitsall(nil)));
break;
default:
threadexitsall(nil);
}ARGEND;

if((chan = chancreate(sizeof(char *), 0)) == nil){
sysfatal("channel error: %r");
}

for(int j = 0; j < 10 ; j++){
for(int i = 0; i < nproc; i++){
proccreate(proc_func, chan, 10240);
}

for(int i = 0; i < nproc; i++){
if(data = recvp(chan)){
free(data);
}
}
fprint(1, "j: %d\n", j);
}

if(nproc)
fprint(1, "EXIT with nproc: %d\n", nproc);

threadexitsall(nil);
}
-

cpu% 6.out -n 10
j: 0
j: 1
j: 2
handler not registred
handler not registred
handler not registred
handler not registred
handler not registred
handler not registred
handler not registred

and stalled forever...



And yes, threadnotify(handler_alarm, 0) in proc_func
does not help.

I don't know how best to get out of this situation.
Probably will have to rewrite the program, so that it does not matter
how many processes have fallen. But it's an increase in complexity.

Regards,
Andrej


--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-M2fc7967213269fe01e89ac5c
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-19 Thread andrey100100100
В Вс, 19/06/2022 в 14:40 +0300, andrey100100...@gmail.com пишет:
> В Вс, 19/06/2022 в 10:32 +, adr пишет:
> > On Sun, 19 Jun 2022, andrey100100...@gmail.com wrote:
> > > No way. All processes must run simultaneously.
> > > NFN limit cannot be bypassed.
> > 
> > Yeah, that's why I said it was silly:
> > > > > The solution is obvious, cancel the process' handlers before
> > > > > it
> > > > > exits so we don't run out of space.
> > > > 
> > > > This was really silly...
> > 
> > The changes I'm testing are not for evading the limit, but for
> > making the handler managment more efficient and specially to avoid
> > the case when a process could remove another process' handler from
> > onnote[].
> 
> Ok.
> 
> 
> More complete example with thread library:
> 
> -
> #include 
> #include 
> #include 
> 
> static int
> handler_alarm(void *, char *msg)
> {
> if(strstr(msg, "alarm")){
> return 1;
> }
> 
> return 0;
> }
> 
> static void
> proc_func(void *c)
> {
> Channel *chan = c;
> 
> int fd, resp_len;
> char req[] = "request";
> char resp[512], *r = nil;
> 
> if(threadnotify(handler_alarm, 1) == 0){
> fprint(1, "handler not registred\n");
> }
> 
> alarm(2000);
> if((fd = dial("udp!185.157.221.201!5678", nil, nil, nil)) >=
> 0){
> alarm(0);
> alarm(2000);
> if(write(fd, req, strlen(req)) == strlen(req)){
> alarm(0);
> alarm(2000);
> if((resp_len = read(fd, resp, sizeof(resp)))
> 0){
> alarm(0);
> if((r = malloc(sizeof(resp))) ==
> nil){
> sysfatal("malloc error: %r");
> }
> memmove(r, resp, sizeof(resp));
> }
> }
> close(fd);
> }
> 

+ alarm(0);

> send(chan, r);
> threadexits(nil);
> }
> 
> int mainstacksize = 5242880;
> 
> void
> threadmain(int argc, char *argv[])
> {
> Channel *chan = nil;
> char *data = nil;
> int nproc = 0;
> 
> ARGBEGIN{
> case 'n':
> nproc = atoi(EARGF(threadexitsall(nil)));
> break;
> default:
> threadexitsall(nil);
> }ARGEND;
> 
> if((chan = chancreate(sizeof(char *), 0)) == nil){
> sysfatal("channel error: %r");
> }
> 
> for(int i = 0; i < nproc; i++){
> proccreate(proc_func, chan, 10240);
> }
> 
> for(int i = 0; i < nproc; i++){
> if(data = recvp(chan)){
> free(data);
> }
> }
> 
> if(nproc)
> fprint(1, "EXIT with nproc: %d\n", nproc);
> 
> threadexitsall(nil);
> }
> -
> 
> cpu% 6.out -n 33
> EXIT with nproc: 33
> 
> with 34:
> 
> cpu% 6.out -n 34
> handler not registred
> 
> and stalled.
> 
> 
> So it is important for me that all processes respond.
> Such use, it seems to me, simplifies the program.
> 
> 

Regards,
Andrej

--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-M1bf9fc766759c5c66a48278e
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-19 Thread andrey100100100
В Вс, 19/06/2022 в 10:32 +, adr пишет:
> On Sun, 19 Jun 2022, andrey100100...@gmail.com wrote:
> > No way. All processes must run simultaneously.
> > NFN limit cannot be bypassed.
> 
> Yeah, that's why I said it was silly:
> > > > The solution is obvious, cancel the process' handlers before it
> > > > exits so we don't run out of space.
> > > 
> > > This was really silly...
> 
> The changes I'm testing are not for evading the limit, but for
> making the handler managment more efficient and specially to avoid
> the case when a process could remove another process' handler from
> onnote[].

Ok.


More complete example with thread library:

-
#include 
#include 
#include 

static int
handler_alarm(void *, char *msg)
{
if(strstr(msg, "alarm")){
return 1;
}

return 0;
}

static void
proc_func(void *c)
{
Channel *chan = c;

int fd, resp_len;
char req[] = "request";
char resp[512], *r = nil;

if(threadnotify(handler_alarm, 1) == 0){
fprint(1, "handler not registred\n");
}

alarm(2000);
if((fd = dial("udp!185.157.221.201!5678", nil, nil, nil)) >=
0){
alarm(0);
alarm(2000);
if(write(fd, req, strlen(req)) == strlen(req)){
alarm(0);
alarm(2000);
if((resp_len = read(fd, resp, sizeof(resp))) >
0){
alarm(0);
if((r = malloc(sizeof(resp))) == nil){
sysfatal("malloc error: %r");
}
memmove(r, resp, sizeof(resp));
}
}
close(fd);
}

send(chan, r);
threadexits(nil);
}

int mainstacksize = 5242880;

void
threadmain(int argc, char *argv[])
{
Channel *chan = nil;
char *data = nil;
int nproc = 0;

ARGBEGIN{
case 'n':
nproc = atoi(EARGF(threadexitsall(nil)));
break;
default:
threadexitsall(nil);
}ARGEND;

if((chan = chancreate(sizeof(char *), 0)) == nil){
sysfatal("channel error: %r");
}

for(int i = 0; i < nproc; i++){
proccreate(proc_func, chan, 10240);
}

for(int i = 0; i < nproc; i++){
if(data = recvp(chan)){
free(data);
}
}

if(nproc)
fprint(1, "EXIT with nproc: %d\n", nproc);

threadexitsall(nil);
}
-

cpu% 6.out -n 33
EXIT with nproc: 33

with 34:

cpu% 6.out -n 34
handler not registred

and stalled.


So it is important for me that all processes respond.
Such use, it seems to me, simplifies the program.


Regards,
Andrej



--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-Mefb1eb17df6e6f347f6c5bf9
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-19 Thread andrey100100100
В Вс, 19/06/2022 в 05:01 +, adr пишет:
> On Sun, 19 Jun 2022, adr wrote:
> > The solution is obvious, cancel the process' handlers before it
> > exits so we don't run out of space.
> 
> This was really silly...
> 
> > Now, is there any reason to not do that in threadexits() when it
> > terminates the process?
> > 
> > Shouldn't threadnotify() cancel only the process' handlers? We are
> > sharing onnote[NFN] and the code as it is right now removes the
> > first handler that match the pointer, it can belong to another
> > process.
> 
> I ended up playing with this (do not register duplicated handlers,
> cancel only the notes of the thread's process and cancel all notes
> when the process exits):
> 
> /sys/src/libthread/sched.c:
> [...]
>     if(t == nil){
>     _threaddebug(DBGSCHED, "all threads gone;
> exiting");
>     cancelnotes(p->pid);
>     _schedexit(p);
>     }
> [...]
> /sys/src/libthread/note.c
> [...]
> int
> threadnotify(int (*f)(void*, char*), int in)
> {
>     int i, frompid, topid;
>     int (*from)(void*, char*), (*to)(void*, char*);
> 
>     if(in){
>     from = nil;
>     frompid = 0;
>     to = f;
>     topid = _threadgetproc()->pid;
>     lock();
>     for(i=0; i     if(onnote[i]==to && onnotepid[i]==topid){
>     unlock();
>     return i     }
>     unlock();
>     }else{
>     from = f;
>     frompid = _threadgetproc()->pid;
>     to = nil;
>     topid = 0;
>     }
>     lock();
>     for(i=0; i     if(onnote[i]==from && onnotepid[i]==frompid){
>     onnote[i] = to;
>     onnotepid[i] = topid;
>     break;
>     }
>     unlock();
>     return i }
> 
> void
> cancelnotes(int pid)
> {
>     int i;
> 
>     lock();
>     for(i=0; i     if(onnotepid[i] == pid){
>     onnote[i] = nil;
>     onnotepid[i] = 0;
>     }
>     unlock();
>     return;
> }
> /sys/include/thread.h
> [...]
> void cancelnotes(int pid);
> [...]


No way. All processes must run simultaneously.
NFN limit cannot be bypassed.

> 
> Anyway, I would like to know a real example when it is useful to
> span a hundred processes using libthread without really exploiting
> threads at all. I mean, we have been streching things a little
> here!
> 

In general, problem not in processes, threads or notes. Problem in
network nature. In the unreliable nature of network communication,
requiring timeouts, packet loss handling, retransmission, etc.

I'm trying to solve it using Plan 9.

In this particular case, I am trying to reduce the total polling time
of, for example, a sensor network by increasing the number of sensors
polled at the same time.

Ready to hear the best solution.

Regards,
Andrej

--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-Mf178309eb46992e6940a5ea4
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-18 Thread andrey100100100
В Сб, 18/06/2022 в 09:22 +, adr пишет:
> On Sat, 18 Jun 2022, adr wrote:
> 
> > On Sat, 18 Jun 2022, andrey100100...@gmail.com wrote:
> > 
> > > -
> > > 
> > > cpu% 6.out | grep end | wc -l
> > >     33
> > > 
> > > 
> > > Problem in unregistered handlers.
> > 
> > But unregistered handlers shouldn't be a problem. The process is
> > been killed when alarm sends the note. That's why the code worked
> > removing the read statement, the alarm is set off and the note is
> > not sent before the process ends. I just don't see why the process
> > is been killed. The documentation describes another behavior. To
> > me it smells like bug barbecue (corrupted onnote?). Maybe I got
> > something wrong, bear with me.
> > 
> > > > Note that you could register the handler in threadmain and
> > > > avoid
> > > > completely this issue, but as I said before, something seems
> > > > wrong
> > > > to me here.
> > > 
> > > I'm don't understand how handler in threadmain would solve the
> > > problem.
> > > I need in 'alarm' on per process basis.
> > 
> > You need alarm() in every process, but you don't need to register
> > the
> > same handler 80 times!
> > 
> > adr.
> 
> I think there is some confussion here, so I'll explain myself a
> little more.
> 
> Lets change your last example to not use libthread:
> 
> #include 
> #include 
> 
> int
> handler_alarm(void *, char *msg)
> {
>  if(strstr(msg, "alarm")){
>  return 1;
>  }
> 
>  return 0;
> }
> 
> int
> test(void)
> {
>  if(atnotify(handler_alarm, 1) == 0){
>  fprint(1, "handler not registered\n");
>  }
> 
>  alarm(10);
>  fprint(1, "start\n");
>  sleep(40);
>  fprint(1, "end\n");
>  alarm(0);
> 
>  return 0;
> }
> 
> void
> main()
> {
>  for(int i = 0; i < 80; i++){
>  test();
>  }
> 
>  exits(nil);
> }
> 
> You see, after the NFNth iteration of test(), onnot[NFN] in atnotify
> will be full, the handlers wont be registered but the code will
> work without any problem. It doesn't matter, the first handler in
> onnot[] will be executed. I fact you only need one handler there, not
> 80, you should move atnotify to main.
> 
> The same should be happening with libthread. I'm really the only
> one smelling a bug here?

Atnotify and threadnotify have different implementation.
it seems that threadnotify is for processes with shared memory,
atnotify for fork() (no shared memory).

But then it is not entirely clear why lock() is used in atnotify?




Regards,
Andrej



--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-Mfea7f52ccd99974d957af810
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-18 Thread andrey100100100
В Сб, 18/06/2022 в 06:53 -0600, Jacob Moody пишет:
> On 6/18/22 03:22, adr wrote:
> > On Sat, 18 Jun 2022, adr wrote:
> > 
> > > On Sat, 18 Jun 2022, andrey100100...@gmail.com wrote:
> > > 
> > > > -
> > > > 
> > > > cpu% 6.out | grep end | wc -l
> > > >     33
> > > > 
> > > > 
> > > > Problem in unregistered handlers.
> > > 
> > > But unregistered handlers shouldn't be a problem. The process is
> > > been killed when alarm sends the note. That's why the code worked
> > > removing the read statement, the alarm is set off and the note is
> > > not sent before the process ends. I just don't see why the
> > > process
> > > is been killed. The documentation describes another behavior. To
> > > me it smells like bug barbecue (corrupted onnote?). Maybe I got
> > > something wrong, bear with me.
> > > 
> > > > > Note that you could register the handler in threadmain and
> > > > > avoid
> > > > > completely this issue, but as I said before, something seems
> > > > > wrong
> > > > > to me here.
> > > > 
> > > > I'm don't understand how handler in threadmain would solve the
> > > > problem.
> > > > I need in 'alarm' on per process basis.
> > > 
> > > You need alarm() in every process, but you don't need to register
> > > the
> > > same handler 80 times!
> > > 
> > > adr.
> > 
> > I think there is some confussion here, so I'll explain myself a
> > little more.
> > 
> > Lets change your last example to not use libthread:
> > 
> > #include 
> > #include 
> > 
> > int
> > handler_alarm(void *, char *msg)
> > {
> >  if(strstr(msg, "alarm")){
> >  return 1;
> >  }
> > 
> >  return 0;
> > }
> > 
> > int
> > test(void)
> > {
> >  if(atnotify(handler_alarm, 1) == 0){
> >  fprint(1, "handler not registered\n");
> >  }
> > 
> >  alarm(10);
> >  fprint(1, "start\n");
> >  sleep(40);
> >  fprint(1, "end\n");
> >  alarm(0);
> > 
> >  return 0;
> > }
> > 
> > void
> > main()
> > {
> >  for(int i = 0; i < 80; i++){
> >  test();
> >  }
> > 
> >  exits(nil);
> > }
> > 
> > You see, after the NFNth iteration of test(), onnot[NFN] in
> > atnotify
> > will be full, the handlers wont be registered but the code will
> > work without any problem. It doesn't matter, the first handler in
> > onnot[] will be executed. I fact you only need one handler there,
> > not
> > 80, you should move atnotify to main.
> > 
> > The same should be happening with libthread. I'm really the only
> > one smelling a bug here?
> 
> No, you've got me convinced something much more wrong is going on.
> Because you're right, our read children shouldn't just be gone,
> we should return from read with an error and then print the "end"
> line.
> I've attempted to reproduce it, trying to remove the libthread/notify
> factors. I've come up with this:
> 
> #include 
> #include 
> 
> static void
> proc_udp(void*)
> {
>     char resp[512];
>     char req[] = "request";
>     int fd;
>     int n;
>     int pid;
> 
>     fd = dial("udp!185.157.221.201!5678", nil, nil, nil);
>     if(fd < 0)
>     exits("can't dial");
> 
>     if(write(fd, req, strlen(req)) != strlen(req))
>     exits("can't write");
> 
>     pid = getpid();
>     fprint(1, "start %d\n", pid);
>     n = read(fd, resp, sizeof(resp)-1);
>     fprint(1, "end %d %d\n", pid, n);
>     exits(nil);
> }
> 
> void
> main(int, char**)
> {
>     int i;
>     Waitmsg *wm;
> 
>     for(i = 0; i < 10; i++){
>     switch(fork()){
>     case -1:
>     sysfatal("fork %r");
>     case 0:
>     proc_udp(nil);
>     sysfatal("ret");
>     default:
>     break;
>     }
>     }
>     for(i = 0; i < 10; i++){
>     wm = wait();
>     print("proc %d died with message %s\n", wm->pid, wm-
> >msg);
>     }
>     exits(nil);
> }
> 
> This code makes it pretty obvious that we are losing some children;
> on my machine this program never exits. I see some portion of the
> readers correctly returning -1, and the parent is able to get their
> Waitmsg but not all of them.
> 

cpu% 6.out
start 20383
start 20390
start 20385
start 20389
start 20387
start 20384
start 20388
start 20381
start 20382
start 20386
end 20390 -1
end 20386 -1
end 20382 -1
end 20381 -1
end 20387 -1
end 20384 -1
proc 20390 died with message 
proc 20384 died with message 
proc 20387 died with message 
proc 20381 died with message 
proc 20382 died with message 
proc 20386 died with message 

'losed' processes stalled in read syscall:

glenda203800:00   0:00   52K Await6.out
glenda203830:00   0:00   48K Pread6.out
glenda203850:00   0:00   48K Pread6.out

Re: [9fans] syscall silently kill processes

2022-06-18 Thread andrey100100100
В Сб, 18/06/2022 в 08:37 +, adr пишет:
> On Sat, 18 Jun 2022, andrey100100...@gmail.com wrote:
> 
> > -
> > 
> > cpu% 6.out | grep end | wc -l
> >     33
> > 
> > 
> > Problem in unregistered handlers.
> 
> But unregistered handlers shouldn't be a problem. The process is
> been killed when alarm sends the note. That's why the code worked
> removing the read statement, the alarm is set off and the note is
> not sent before the process ends. I just don't see why the process
> is been killed. 

The process dies, because the handler that suppresses the default
behavior on note 'alarm' is not registered. And the default behavior is
death.

> The documentation describes another behaivor. To
> me it smells like bug barbecue (corrupted onnote?). Maybe I got
> something wrong, bear with me.
> 
> > > Note that you could register the handler in threadmain and avoid
> > > completely this issue, but as I said before, something seems
> > > wrong
> > > to me here.
> > 
> > I'm don't understand how handler in threadmain would solve the
> > problem.
> > I need in 'alarm' on per process basis.
> 
> You need alarm() in every process, but you don't need to register the
> same handler 80 times!


Perhaps I need different handlers for different processes.
Or, for some processes, I need a default behavior, and for some others,
a handler.

> 
> adr.
> 

Regards,
Andrej

--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-Mc5582399d6c559ec53eddd59
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-18 Thread andrey100100100
В Пт, 17/06/2022 в 21:15 +, adr пишет:
> On Fri, 17 Jun 2022, andrey100100...@gmail.com wrote:
> > Seems like noted() call not needed in user code.
> 
> noted() is only needed when using the syscall notify, when using
> atnotify() (or threadnotify) you don't need it, as it is said in
> notify(2) and you did correctly in your first example. threadnotify
> doesn't kill your process if there is no space free in onnote[],
> onnotepid[], the handler is not registered, that's all. alarm()
> should send the note to the process and the first handler registered
> with the note "alarm" should be executed. Your handler checked for
> the note and returned non zero, the process should continue. When
> read is interrupted, it should return an error, the process should
> not be killed. Here is the issue. Comment the read statement and
> there will be the same number of "end"s as "start"s.
> 

Мore clear example, which demonstrate crux of the problem:

-
#include 
#include 
#include 

static int
handler_alarm(void *, char *msg)
{
if(strstr(msg, "alarm")){
return 1;
}

return 0;
}

static void
proc_func(void *)
{
if(threadnotify(handler_alarm, 1) == 0){
fprint(1, "handler not registred\n");
}

alarm(2000);
fprint(1, "start\n");
sleep(1);
fprint(1, "end\n");
alarm(0);

threadexits(nil);
}

int mainstacksize = 5242880;

void
threadmain(int argc, char *argv[])
{
for(int i = 0; i < 80; i++){
proccreate(proc_func, nil, 10240);
}

sleep(5000);
threadexitsall(nil);
}
-

cpu% 6.out | grep end | wc -l
 33


Problem in unregistered handlers.



> Note that you could register the handler in threadmain and avoid
> completely this issue, but as I said before, something seems wrong
> to me here.
> 

I'm don't understand how handler in threadmain would solve the problem.
I need in 'alarm' on per process basis.






Regards,
Andrej

--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-M2bf5df4e0184bdff80c9eee9
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


Re: [9fans] syscall silently kill processes

2022-06-17 Thread andrey100100100
В Пт, 17/06/2022 в 10:11 -0600, Jacob Moody пишет:
> On 6/17/22 09:06, andrey100100...@gmail.com wrote:
> > В Пт, 17/06/2022 в 08:11 -0600, Jacob Moody пишет:
> > > On 6/17/22 07:46, Thaddeus Woskowiak wrote:
> > > > I believe threadnotify() should be called from threadmain() to
> > > > properly register the handler in the rendez group
> > > 
> > > This is incorrect, according to thread(2):
> > > 
> > > "The thread library depends on all procs
> > > being in the same rendezvous group"
> > 
> > 
> > From sleep(2):
> > 
> >     Alarm causes an alarm note (see notify(2)) to be sent to the
> >     invoking process after the number of milliseconds given by
> >     the argument.
> > 
> > Mean to be sent only to the invoking process, NOT to the process
> > group.
> 
> Yes this is correct, If I implied otherwise I apologize. My point
> with
> pointing out that excerpt is that groups likely had nothing to do
> with this.
> 
> > > 
> > > The issue here is that your note handler has to call noted,
> > > you are returning from the handler without actually resuming the
> > > program.
> > > You either need to call noted(NCONT) to resume execution or
> > > noted(NDFLT)
> > > to stop execution.
> > > 
> > > An excerpt from notify(2):
> > > 
> > > "A notification handler must finish either by exiting the
> > > program or by calling noted; if the handler returns the
> > > behavior is undefined and probably erroneous."
> > > 
> > > So you are indeed observing undefined behavior.
> > > 
> > 
> > With:
> > 
> > 
> > static int
> > handler_alarm(void *, char *msg)
> > {
> >     if(strstr(msg, "alarm")){
> >     noted(NCONT);
> >     return 1;
> >     }
> > 
> >     return 0;
> > }
> > 
> > result the same:
> > 
> > cpu% 6.out | grep end | wc -l
> >  33
> > 
> > 
> > And noted(NCONT) may be needed, when process recieved many (2 and
> > more)
> > notes at once.
> > 
> > May be something wrong  with interrupted an incomplete  system
> > call?
> 
> You _always_ should call either noted(NCONT) or noted(NDFLT).

But from atnotify(2) (section 'Atnotify'):

  When the system
  posts a note to the process, each handler registered with
  atnotify is called with arguments as described above until
  one of the handlers returns non-zero.  Then noted is called
  with argument NCONT.  If no registered function returns
  non-zero, atnotify calls noted with argument NDFLT.

from /sys/src/libc/port/atnotify.c :


static
void
notifier(void *v, char *s)
{
int i;

for(i=0; i But you are correct in that this wasn't the exact issue. I poked
> around with the code a bit. I rewrote it to just use
> fork(), and I got all 80 "end" messages. 

Yes, with fork() is working:

--
#include 
#include 

static int
handler_alarm(void *, char *msg)
{
if(strstr(msg, "alarm"))
return 1;

return 0;
}

static void
proc_udp(void *)
{
char resp[512];
char req[] = "request";
int fd;

atnotify(handler_alarm, 1);

if((fd = dial("udp!185.157.221.201!5678", nil, nil, nil)) >=
0){
if(write(fd, req, strlen(req)) == strlen(req)){
fprint(1, "start\n");
alarm(2000);
read(fd, resp, sizeof(resp));
alarm(0);
fprint(1, "end\n");
}
close(fd);
}

}

void
main(int argc, char *argv[])
{
for(int i = 0; i < 80; i++){
switch(fork()){
case -1:
sysfatal("fork: %r");
case 0:
proc_udp(nil);
exits(nil);
}
}

sleep(5000);
exits(nil);
}
--

cpu% 6.out | grep end | wc -l
 80

But with rfork(RFPROC|RFMEM|RFNOWAIT) (the same, how in proccreate)
not:

cpu% 6.out | grep end | wc -l
  6

strange...

> So I suspected
> libthread had some arbitrary limit:
> 
> #define NFN 33
> #define ERRLEN  48
> typedef struct Note Note;
> struct Note
> {
>     Lock    inuse;
>     Proc    *proc;  /* recipient */
>     char    s[ERRMAX];  /* arg2 */
> };
> 
> static Note notes[128];
> static Note *enotes = notes+nelem(notes);
> static int  (*onnote[NFN])(void*, char*);
> static int  onnotepid[NFN];
> static Lock onnotelock;
> 
> int
> threadnotify(int (*f)(void*, char*), int in)
> {
>     int i, topid;
>     int (*from)(void*, char*), (*to)(void*, char*);
> 
>     if(in){
>     from = nil;
>     to = f;
> 

Re: [9fans] syscall silently kill processes

2022-06-17 Thread andrey100100100
В Пт, 17/06/2022 в 08:11 -0600, Jacob Moody пишет:
> On 6/17/22 07:46, Thaddeus Woskowiak wrote:
> > I believe threadnotify() should be called from threadmain() to
> > properly register the handler in the rendez group
> 
> This is incorrect, according to thread(2):
> 
> "The thread library depends on all procs
> being in the same rendezvous group"


>From sleep(2):

Alarm causes an alarm note (see notify(2)) to be sent to the
invoking process after the number of milliseconds given by
the argument.

Mean to be sent only to the invoking process, NOT to the process group.

> 
> The issue here is that your note handler has to call noted,
> you are returning from the handler without actually resuming the
> program.
> You either need to call noted(NCONT) to resume execution or
> noted(NDFLT)
> to stop execution.
> 
> An excerpt from notify(2):
> 
> "A notification handler must finish either by exiting the
> program or by calling noted; if the handler returns the
> behavior is undefined and probably erroneous."
> 
> So you are indeed observing undefined behavior.
> 

With:


static int
handler_alarm(void *, char *msg)
{
if(strstr(msg, "alarm")){
noted(NCONT);
return 1;
}

return 0;
}


result the same:

cpu% 6.out | grep end | wc -l
 33


And noted(NCONT) may be needed, when process recieved many (2 and more)
notes at once.

May be something wrong  with interrupted an incomplete  system call?


> 
> Hope this helps,
> moody
> 


Regards,
Andrej





--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-M4fa69df14eff60273727c92b
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription


[9fans] syscall silently kill processes

2022-06-17 Thread andrey100100100
Hi all!

Strange behavior of syscall 'read' with signal 'alarm' in followed
simple program (ip/port - not matter):

---
#include 
#include 
#include 

static int
handler_alarm(void *, char *msg)
{
if(strstr(msg, "alarm"))
return 1;

return 0;
}

static void
proc_udp(void *)
{
char resp[512];
char req[] = "request";
int fd;

threadnotify(handler_alarm, 1);

if((fd = dial("udp!185.157.221.201!5678", nil, nil, nil)) >=
0){
if(write(fd, req, strlen(req)) == strlen(req)){
fprint(1, "start\n");
alarm(2000);
read(fd, resp, sizeof(resp));
alarm(0);
fprint(1, "end\n");
}
close(fd);
}

threadexits(nil);
}

int mainstacksize = 5242880;

void
threadmain(int argc, char *argv[])
{
for(int i = 0; i < 80; i++){
proccreate(proc_udp, nil, 10240);
}

sleep(5000);
threadexitsall(nil);
}
---


cpu% 6.out | grep end | wc -l
 33

sometimes little more or less
but

cpu% 6.out | grep start | wc -l
 80
 
always.

Testing on Miller's RPi and 9front (amd64 & RPi 2)


Why does read() kill process?
Why not always?
Why number of 'ended' processes arond 33?
This is normal behavior?
How to fix the program so that the processes do not lost?


Can someone point me in the right direction?


Thanks!
Andrey

--
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-M6b9bfae581b00133c66b93c2
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription