[9fans] syscall silently kill processes
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
Re: [9fans] syscall silently kill processes
В Пт, 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
Re: [9fans] syscall silently kill processes
В Пт, 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
В Пт, 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
В Сб, 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
В Сб, 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 g
Re: [9fans] syscall silently kill processes
В Сб, 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
В Вс, 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(&onnotelock); > for(i=0; i if(onnote[i]==to && onnotepid[i]==topid){ > unlock(&onnotelock); > return i } > unlock(&onnotelock); > }else{ > from = f; > frompid = _threadgetproc()->pid; > to = nil; > topid = 0; > } > lock(&onnotelock); > for(i=0; i if(onnote[i]==from && onnotepid[i]==frompid){ > onnote[i] = to; > onnotepid[i] = topid; > break; > } > unlock(&onnotelock); > return i } > > void > cancelnotes(int pid) > { > int i; > > lock(&onnotelock); > for(i=0; i if(onnotepid[i] == pid){ > onnote[i] = nil; > onnotepid[i] = 0; > } > unlock(&onnotelock); > 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
В Вс, 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
В Вс, 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
В Вс, 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
В Вс, 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
В Пн, 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
В Пн, 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
В Пн, 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(&onnotelock); > for(i=0; i if(onnote[i]==to && onnotepid[i]==topid){ > unlock(&onnotelock); > return i } > unlock(&onnotelock); > }else{ > from = f; > frompid = (in < -1)? -1 : _threadgetproc()->pid; > to = nil; > topid = 0; > } > lock(&onnotelock); > for(i=0; i if(onnote[i]==from && onnotepid[i]==frompid){ > onnote[i] = to; > onnotepid[i] = topid; > break; > } > unlock(&onnotelock); > return i } > > void > cancelnotes(int pid) > { > int i; > > lock(&onnotelock); > for(i=0; i if(onnotepid[i] == pid){ > onnote[i] = nil; > onnotepid[i] = 0; > } > unlock(&onnotelock); > 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
В Пн, 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(&onnotelock); > > > for(i=0; i > > if(onnote[i]==to && onnotepid[i]==topid){ > > > unlock(&onnotelock); > > > return i > > } > > > unlock(&onnotelock); > > > }else{ > > > from = f; > > > frompid = (in < -1)? -1 : _threadgetproc()->pid; > > > to = nil; > > > topid = 0; > > > } > > > lock(&onnotelock); > > > for(i=0; i > > if(onnote[i]==from && onnotepid[i]==frompid){ > > > onnote[i] = to; > > > onnotepid[i] = topid; > > > break; > > > } > > > unlock(&onnotelock); > > > return i > > } > > > > > > void > > > cancelnotes(int pid) > > > { > > > int i; > > > > > > lock(&onnotelock); > > > for(i=0; i > > if(onnotepid[i] =
Re: [9fans] syscall silently kill processes
В Вт, 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
В Вт, 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
В Вт, 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(&onnotelock); > - 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(&onnotelock); > + return 1; > + } > + for(i=0; i + if(onnoteall[i] == nil){ > + onnoteall[i] = f; > + break; > + } > + unlock(&onnotelock); > + return i + } > + > + /* remove note for all processes */ > + if(in == -1){ > + for(i=0; i + if(onnoteall[i] == f){ > + onnoteall[i] = nil; > + break; > + } > + unlock(&onnotelock); > + 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(&onnotelock); > + return j + } > +