9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
From: adr <adr@SDF.ORG>
To: 9fans <9fans@9fans.net>
Subject: Re: [9fans] syscall silently kill processes
Date: Tue, 28 Jun 2022 18:19:53 +0000 (UTC)	[thread overview]
Message-ID: <4cb721cd-616d-8f86-e499-ad9da41c40a2@SDF.ORG> (raw)
In-Reply-To: <87cff69b-4b82-8466-a34f-13c7eda24fc9@SDF.ORG>

On Tue, 28 Jun 2022, adr wrote:
> 
> 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.

This just evade going through the arrays twice. For the current
value of NFN it doesn't make too much a difference, note that this
structures are locked. It just was hurting my eyes.
--- /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,7 +5,6 @@

  int   _threadnopasser;

-#define        NFN             33
  #define       ERRLEN  48
  typedef struct Note Note;
  struct Note
@@ -17,62 +16,161 @@

  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, n;

-       if(in){
-               from = nil;
-               to = f;
-               topid = _threadgetproc()->pid;
-       }else{
-               from = f;
-               to = nil;
-               topid = 0;
-       }
        lock(&onnotelock);
-       for(i=0; i<NFN; i++)
-               if(onnote[i]==from){
-                       onnote[i] = to;
-                       onnotepid[i] = topid;
+
+       /* add note for all processes */
+       if(in < -1){
+               n = -1;
+               for(i=0; i<NFN; i++){
+                       if(onnoteall[i] == f){
+                               unlock(&onnotelock);
+                               return 1;
+                       }
+                       if(onnoteall[i]==nil && n==-1)
+                               n = i;
+               }
+               if(n > -1)
+                       onnoteall[n] = f;
+               unlock(&onnotelock);
+               return n>-1;
+       }
+
+       /* remove note for all processes */
+       if(in == -1){
+               for(i=0; i<NFN; i++)
+                       if(onnoteall[i] == f){
+                               onnoteall[i] = nil;
+                               break;
+                       }
+               unlock(&onnotelock);
+               return i<NFN;
+       }
+
+       /* remove note for current process */
+       if(!in){
+               for(i=0; i<onnotesize; i++){
+                       if(onnote[i]!=nil && onnote[i]->pid==_threadgetproc()->pid){
+                               for(j=0; j<NFN; j++){
+                                       if(onnote[i]->fn[j] == f){
+                                               onnote[i]->fn[j] = 0;
+                                               break;
+                                       }
+                               }
+                               unlock(&onnotelock);
+                               return j<NFN;
+                       }
+               }
+               unlock(&onnotelock);
+               return 0;
+       }
+
+       /* add note for current process */
+       for(i=0; i<onnotesize; i++)
+               if(onnote[i] && onnote[i]->pid==_threadgetproc()->pid)
+                       break;
+
+       /* process has already a slot */
+       if(i < onnotesize){
+               n = -1;
+               for(j=0; j<NFN; j++){
+                       if(onnote[i]->fn[j] == f){
+                               unlock(&onnotelock);
+                               return 1;
+                       }
+                       if(onnote[i]->fn[j] == nil)
+                               n = j;
+               }
+               if(n > -1)
+                       onnote[i]->fn[n] = f;
+               unlock(&onnotelock);
+               return n>-1;
+ 
+       }
+
+       for(i=0; i<onnotesize; i++)
+               if(!onnote[i])
+                       break;
+
+       /* there is no free slot */
+       if(i == onnotesize){
+               onnotesize += PPCHUNK;
+               onnote = realloc(onnote, onnotesize*sizeof(uintptr));
+               if(!onnote){
+                       unlock(&onnotelock);
+                       sysfatal("Malloc of size %d failed: %r", onnotesize*sizeof(uintptr));
+               }
+               memset(onnote+i+1, 0, PPCHUNK-1);
+       }
+
+       onnote[i]=mallocz(sizeof(Onnote), 1);
+       if(!onnote[i]){
+               unlock(&onnotelock);
+               sysfatal("Malloc of size %d failed: %r", sizeof(Onnote));
+       }
+       onnote[i]->pid = _threadgetproc()->pid;
+       onnote[i]->fn[0] = f;
+       unlock(&onnotelock);
+       return 1;
+}
+
+void
+threadcancelnotes(int pid)
+{
+       int i;
+
+       lock(&onnotelock);
+       for(i=0; i<onnotesize; i++)
+               if(onnote[i] && onnote[i]->pid==pid){
+                       free(onnote[i]);
+                       onnote[i] = nil;
                        break;
                }
        unlock(&onnotelock);
-       return i<NFN;
+       return;
  }

  static void
  delayednotes(Proc *p, void *v)
  {
-       int i;
+       int i, j, all;
        Note *n;
-       char s[ERRMAX];
-       int (*fn)(void*, char*);
+       int (*f)(void*, char*);

        if(!p->pending)
                return;

        p->pending = 0;
+       all = j = 0;
        for(n=notes; n<enotes; n++){
                if(n->proc == p){
-                       strcpy(s, n->s);
-                       n->proc = nil;
-                       unlock(&n->inuse);
-
-                       for(i=0; i<NFN; i++){
-                               if(onnotepid[i]!=p->pid || (fn = onnote[i])==nil)
-                                       continue;
-                               if((*fn)(v, s))
-                                       break;
+                       for(i=0; i<NFN; i++)
+                               if(f=onnoteall[i])
+                                       if((*f)(v, n->s)){
+                                               all = 1;
+                                               break;
+                                       }
+                       if(!all){
+                               for(i=0; i<onnotesize; i++)
+                                       if(onnote[i] && onnote[i]->pid==p->pid){
+                                               for(j=0; j<NFN; j++)
+                                                       if(f=onnote[i]->fn[j])
+                                                               if((*f)(v, n->s))
+                                                                       break;
+                                               break;
+                                       }
                        }
-                       if(i==NFN){
-                               _threaddebug(DBGNOTE, "Unhandled note %s, proc %p", n->s, p);
+                       if(!all && (i==onnotesize || j==NFN)){
+                               _threaddebug(DBGNOTE, "Unhandled note %s, proc %p\n", n->s, p);
                                if(v != nil)
                                        noted(NDFLT);
                                else if(strncmp(n->s, "sys:", 4)==0)
@@ -79,6 +177,8 @@
                                        abort();
                                threadexitsall(n->s);
                        }
+                       n->proc = nil;
+                       unlock(&n->inuse);
                }
        }
  }
@@ -94,7 +194,7 @@
                noted(NDFLT);

        if(_threadexitsallstatus){
-               _threaddebug(DBGNOTE, "Threadexitsallstatus = '%s'", _threadexitsallstatus);
+               _threaddebug(DBGNOTE, "Threadexitsallstatus = '%s'\n", _threadexitsallstatus);
                _exits(_threadexitsallstatus);
        }

--- /tmp/sched.c
+++ /sys/src/libthread/sched.c
@@ -157,6 +157,7 @@
                t = runthread(p);
                if(t == nil){
                        _threaddebug(DBGSCHED, "all threads gone; exiting");
+                       threadcancelnotes(p->pid);
                        unlinkproc(p);
                        _schedexit(p);  /* frees proc */
                }
--- /tmp/thread.h
+++ /sys/include/thread.h
@@ -97,6 +97,7 @@
  void  threadkillgrp(int);     /* kill threads in group */
  void  threadmain(int argc, char *argv[]);
  int   threadnotify(int (*f)(void*, char*), int in);
+void threadcancelnotes(int pid);
  int   threadid(void);
  int   threadpid(int);
  int   threadsetgrp(int);              /* set thread group, return old */
--- /tmp/threadimpl.h
+++ /sys/src/libthread/threadimpl.h
@@ -192,3 +192,15 @@
  #define       _threaddebug(flag, ...) if((_threaddebuglevel&(flag))==0){}else _threadprint(__VA_ARGS__)

  #define ioproc_arg(io, type)  (va_arg((io)->arg, type))
+
+#define        PPCHUNK 100
+#define        NFN 33
+typedef struct Onnote Onnote;
+struct Onnote
+{
+       int pid;
+       int (*fn[NFN])(void*, char*);
+};
+extern Onnote **onnote;
+extern int onnotesize;
+void _threadnote(void*, char*);

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

  parent reply	other threads:[~2022-06-28 18:20 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-17  9:37 andrey100100100
2022-06-17 13:46 ` Thaddeus Woskowiak
2022-06-17 14:11   ` Jacob Moody
2022-06-17 14:39     ` Thaddeus Woskowiak
2022-06-17 15:06     ` andrey100100100
2022-06-17 16:08       ` Skip Tavakkolian
2022-06-17 16:11         ` Skip Tavakkolian
2022-06-17 16:16           ` Skip Tavakkolian
2022-06-17 17:42             ` adr
2022-06-17 16:11       ` Jacob Moody
2022-06-17 18:48         ` andrey100100100
2022-06-17 19:28           ` Jacob Moody
2022-06-17 21:15           ` adr
2022-06-18  6:40             ` andrey100100100
2022-06-18  8:37               ` adr
2022-06-18  9:22                 ` adr
2022-06-18 12:53                   ` Jacob Moody
2022-06-18 22:03                     ` andrey100100100
2022-06-19  5:54                     ` adr
2022-06-19  6:13                       ` Jacob Moody
2022-06-18 22:22                   ` andrey100100100
2022-06-18 16:57                 ` andrey100100100
2022-06-19  2:40                   ` adr
2022-06-19  5:01                     ` adr
2022-06-19  8:52                       ` andrey100100100
2022-06-19 10:32                         ` adr
2022-06-19 11:40                           ` andrey100100100
2022-06-19 12:01                             ` andrey100100100
2022-06-19 15:10                           ` andrey100100100
2022-06-19 16:41                             ` adr
2022-06-19 21:22                               ` andrey100100100
2022-06-19 21:26                                 ` andrey100100100
2022-06-20  4:41                                 ` adr
2022-06-20  5:39                                   ` andrey100100100
2022-06-20  5:59                                   ` adr
2022-06-20 15:56                                     ` andrey100100100
2022-06-20 22:29                                       ` Skip Tavakkolian
2022-06-21  7:07                                         ` andrey100100100
2022-06-21 11:26                                           ` adr
2022-06-21 13:03                                             ` andrey100100100
2022-06-21 13:22                                               ` adr
2022-06-28 15:28                                                 ` adr
2022-06-28 16:43                                                   ` ori
2022-06-28 18:19                                                   ` adr [this message]
2022-06-28 18:28                                                     ` adr
2022-06-28 19:09                                                   ` andrey100100100
2022-06-28 19:42                                                     ` adr
2022-06-29 13:14                                                       ` adr
2022-06-21 13:47                                             ` andrey100100100
2022-06-21  7:22                                         ` adr

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4cb721cd-616d-8f86-e499-ad9da41c40a2@SDF.ORG \
    --to=adr@sdf.org \
    --cc=9fans@9fans.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).