delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2015/10/04/06:37:02

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
X-Recipient: djgpp AT delorie DOT com
Message-ID: <561101C4.7040701@gmx.de>
Date: Sun, 04 Oct 2015 12:39:00 +0200
From: "Juan Manuel Guerrero (juan DOT guerrero AT gmx DOT de) [via djgpp AT delorie DOT com]" <djgpp AT delorie DOT com>
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.13) Gecko/20101206 SUSE/3.1.7 Thunderbird/3.1.7
MIME-Version: 1.0
To: djgpp AT delorie DOT com
Subject: Re: dlclose not removing dependency dxes
References: <CAA2C=vAwcH9pHN63=Mskr9L016yAAJ6KkMPeuO9o_2cV7Pd0Kw AT mail DOT gmail DOT com> <CAA2C=vDDN8UqGpbAzkba19Syq-1mLsBPAuSzSPWue_S2TYf_XQ AT mail DOT gmail DOT com> <b8759e89-e375-4647-a9eb-64543cc49748 AT googlegroups DOT com> <CAA2C=vDSknbCKHzUA954weavLj16nXuDyP_Ggi+SmLJ_e-U_KA AT mail DOT gmail DOT com> <CAA2C=vAdzu+ebq1mEsoqwkxJcYR+2EZdKJ3d5XxOZRCytL6z8w AT mail DOT gmail DOT com> <952a68b4-223b-4222-b456-35514bb8b7eb AT googlegroups DOT com> <CAA2C=vA0sYw19muvCeX-mY3hegXnpt2P76wn73+fbdJfdj+DwQ AT mail DOT gmail DOT com>
In-Reply-To: <CAA2C=vA0sYw19muvCeX-mY3hegXnpt2P76wn73+fbdJfdj+DwQ@mail.gmail.com>
X-Provags-ID: V03:K0:7PK+6B3NkAeSWVyg7lp59EigiiK3QaqVt+KaHOil7boISh/sVvQ
UT7LAmbThS5B2SzqBmy6P9DfiM0QHnKSbT9ku4dJvwy9hO9uVSe7zj/yndeOTjM/MLKARjg
0lECK09CbbXEptARE+yEIs34+VtOjhVxuWJ2wqEDIz8TRyxCjEQsnXAKT+c+I24P1LRVJAv
MjXOkinMe4je+A0GjW+hg==
X-UI-Out-Filterresults: notjunk:1;V01:K0:GFYFzkRnyng=:CreYK9nOyYl2onVA9l1Q3E
N69njXEQ/meFm+lbd8ygFUHok3iBL73t7D2Ifwdn2PrWmVKWtKrXUA3YjaTLk3ddK+nRM3Oul
8U0XgMZ9Z0PD0tDJMp3wFXASOBJcIzeUBmY94c/8AVRiUV892bOSrtTqcnl8L97cZMdlgQDmu
Ev7vdTrLYzEYx6SPdMNzsMbjNT9drjVLSItaUxeTDACEsuw/C08yt/8p2+GL+3ish/YDASL/B
akGhEPwK1XZGvmOO9I9XC45NWt4klzRZh6pZ4+fivPUzWnOiJI5m0MIjfijG+qLACWh9tE+07
XgnQmXLClEBl8FhAXBvbsVagjm56dO7FE1fF5xUr0kNx+vSUea8z14/zaoQKpFLgyGud5m7Yc
t5pm6F2xzEirT4Kj8mgd8OkEC9HgZSNZZiR1TR0R+hUCBKtO4RsIzB+daIScRHSpos/KQChne
47SRdNXjeh53LFcf4YEb1sCaLTaHx+2rVyaaJBJXqytnXPzHvbs31MU7ywCMIJy7mwJpkATnN
F1Js1FktTunDIEdKqabgE3wzVk6WBUGZPgaUk3F0iCgCWl7GNtIE3izyUAmd2kMpIC45eJBK4
sDl6OroNry1p02XVmioECfUTNrWCl+7K2GwwEAp9D+Poy94lSNoWZN4y5VobOwBLuy6XAmHIr
XXDB1Ch7CuteAGIejWgWjPkMn8Dn3jxyPWF/cDGlBto7ztv7c/TY7MOmm5WKewxJa37qXg8hT
umuEOFvc+FyyHoUnJ4NC+Pqf2DReSiQXeIBhuc+RxtA9/hpFKTCIa76JIiBrCQkdL8C2sAoGi
K301WAu
Reply-To: djgpp AT delorie DOT com

Am 01.10.2015 15:56, schrieb Ozkan Sezer (sezeroz AT gmail DOT com) [via djgpp AT delorie DOT com]:
> On 10/1/15, Juan Manuel Guerrero (juan DOT guerrero AT gmx DOT de) [via
> djgpp AT delorie DOT com]<djgpp AT delorie DOT com>  wrote:
>> On Thursday, October 1, 2015 at 9:35:24 AM UTC+2, Ozkan Sezer
>> (sezeroz AT gmail DOT com) [via djgpp AT delorie DOT com] wrote:
>>> On 9/27/15, Ozkan Sezer<sezeroz AT gmail DOT com>  wrote:
>>>> On 9/26/15, Juan Manuel Guerrero (juan DOT guerrero AT gmx DOT de) [via
>>>> djgpp AT delorie DOT com]<djgpp AT delorie DOT com>  wrote:
>>>>> On Friday, September 25, 2015 at 7:21:47 PM UTC+2, Ozkan Sezer
>>>>> (sezeroz AT gmail DOT com) [via djgpp AT delorie DOT com] wrote:
>>>>>> On 9/25/15, Ozkan Sezer<sezeroz AT gmail DOT com>  wrote:
>>>>>>> AFAICS, dlclose()ing of a dxe doesn't remove its dependency dxes
>>>>>>> along
>>>>>>> with it, which will result in unnecessarily occupied memory which
>>>>>>> may
>>>>>>> prove fatal upon multiple dlopen()/dlclose() of a dxe with deps.
>>>>>>> This
>>>>>>> needs addressing.
>>>>>>>
>>>>>>
>>>>>> My last argument was inaccurate and misleading. Here's better:
>>>>>>
>>>>>> One has a.dxe and b.dxe; a.dxe depends on b.dxe.  Do dlopen a.dxe
>>>>>> and b.dxe is opened implicitly.  Do dlcose a.dxe, and b.dxe stays
>>>>>> open still occupying its memory.  The memory occupied by the unused
>>>>>> b.dxe might be needed by the app but will be unavailable to it.
>>>>>> Further dlopen calls for a.dxe will increment the refcount for b.dxe
>>>>>> which never gets decremented.
>>>>>
>>>>>
>>>>> Can you provide a minimal sample code to demonstrate the issue?
>>>>>
>>>>> Regards,
>>>>> Juan M. Guerrero
>>>>>
>>>>
>>>> =======================================
>>>>
>>>> $ cat 12.c
>>>> extern int my_func2();
>>>> int my_func1() {
>>>>    return my_func2();
>>>> }
>>>> $ gcc -c 12.c
>>>> $ dxe3gen -o a.dxe -P b.dxe -U 12.o
>>>> $ dxe3gen --show-exp a.dxe
>>>> _my_func1
>>>> $ dxe3gen --show-dep a.dxe
>>>> b.dxe
>>>>
>>>> =======================================
>>>>
>>>> $ cat 13.c
>>>> int my_func2() {
>>>>    return -1;
>>>> }
>>>> $ gcc -c 13.c
>>>> $ dxe3gen -o b.dxe 13.o
>>>> $ dxe3gen --show-exp b.dxe
>>>> _my_func2
>>>>
>>>> =======================================
>>>>
>>>> $ cat 11.c
>>>> #include<dlfcn.h>
>>>> #include<stdio.h>
>>>>
>>>> void *my_dxe1;
>>>> int (*my_f)();
>>>>
>>>> int main (void) {
>>>>    my_dxe1 = dlopen("a.dxe",0);
>>>>    if (!my_dxe1) {
>>>>      printf("dlopen() failed\n");
>>>>      return 1;
>>>>    }
>>>>    dlclose(my_dxe1);
>>>>
>>>>    my_f = dlsym(RTLD_DEFAULT,"_my_func1");
>>>>    if(!my_f) {
>>>>      printf("a.dxe not loaded\n");
>>>>    }
>>>>    else {
>>>>      printf("a.dxe:my_func1(): %p\n",my_f);
>>>>    }
>>>>
>>>>    my_f = dlsym(RTLD_DEFAULT,"_my_func2");
>>>>    if(!my_f) {
>>>>      printf("b.dxe not loaded\n");
>>>>    }
>>>>    else {
>>>>      printf("b.dxe:my_func2(): %p\n",my_f);
>>>>      printf("b.dxe:my_func2() returns: %d\n",my_f());
>>>>    }
>>>>
>>>>    return 0;
>>>> }
>>>>
>>>> $ gcc -Wall -W 11.c
>>>>
>>>> =======================================
>>>>
>>>> $ a.exe>  a.log
>>>> $ cat a.log
>>>> a.dxe not loaded
>>>> b.dxe:my_func2(): 95830
>>>> b.dxe:my_func2() returns: -1
>>>>
>>>
>>> PING? Any ideas? (Sorry that I brought the issue
>>> but have no patch for it myself.)
>>
>>
>> An inspection of your sample code and dldemo.cpp shows that it seems to be
>> that it is the user's responsibility to explicitly dlclose every dlopen'ed
>> modules.
>
> The thing is, the dependency dxe, i.e. b.dxe in my example,
> is implicitly dlopen()ed and I won't ever have the handle for it.
>
>> This is what an inspection of dldemo.cpp shows.
>> This may not be what you expected from unix but I assume that no DJGPP
>> developer has really promised that the behaviour would be identical to unix
>> behaviour.
>> Neither less I will inspect the issue during week-end but I do not promise
>> that a fix will be possible.
>>
>
> Thanks.
>
> --
> O.S.


Below is a patch that will implement ref-counting for implicitly loaded modules
by other ones.  Please not that this ref-counting only works for dlopen/dlclose.
There may be other loading mechanisms that suffer from the same issue and that
will not be fixed by this modification.
The patch is intended for the main branch but should work on v2_05_1 as well.

Regards,
Juan M. Guerrero




2015-10-03  Juan Manuel Guerrero  <juan DOT guerrero AT gmx DOT de>

	* djgpp/src/libc/dxe/dlopen.c:  Added reference counting support for implicitly loaded DXE modules by dlopen.





diff -aprNU5 djgpp.orig/src/libc/dxe/dlopen.c djgpp/src/libc/dxe/dlopen.c
--- djgpp.orig/src/libc/dxe/dlopen.c	2015-10-03 15:18:20 -29907
+++ djgpp/src/libc/dxe/dlopen.c	2015-10-04 11:40:00 -29907
@@ -36,14 +36,16 @@

  #ifndef ELOOP
  #define ELOOP EMLINK
  #endif

+#define __DEBUG_DXE3__  0	/*  Prints struct __dxe_handle members.  Always commited as 0.  */
+
  /* private stack */
-typedef struct stk_node {
+typedef struct __stk_node {
    const char *name;
-  struct stk_node *next;
+  struct __stk_node *next;
  } stk_node;

  /* Exported symbols table entry */
  typedef struct
  {
@@ -57,22 +59,29 @@ typedef struct
    unsigned short n_rel_relocs;
    unsigned short n_abs_relocs;
    char name [1];		/* expanded as needed */
  } __attribute__((packed)) unres_table_entry;

+/* This is a linked list of implizitly loaded dxe modules.  */
+typedef struct __linked_list {
+  struct __dxe_handle *handle;	/* Pointer to next implicitly open module by this module */
+  struct __linked_list *next;	/* Next entry in list  */
+} dxe_handle_list;
+
  /* This is the private dxe_h structure */
  typedef struct __dxe_handle
  {
-  struct __dxe_handle *next;		/* Pointer to next module in chain */
-  char fname[FILENAME_MAX];		/* Full module pathname */
-  int mode;				/* Module open mode */
-  int inuse;				/* In-use counter */
-  int n_exp_syms;			/* Number of entries in export table */
-  exp_table_entry **exp_table;		/* Exported symbols table */
-  char *header;				/* The resident portion of header */
-  char *section;			/* code+data+bss section */
-  long _fini;				/* finalization */
+  struct __dxe_handle *next;			/* Pointer to next module in chain */
+  char fname[FILENAME_MAX];			/* Full module pathname */
+  int mode;					/* Module open mode */
+  int in_use;					/* In-use counter */
+  int n_exp_syms;				/* Number of entries in export table */
+  exp_table_entry **exp_table;			/* Exported symbols table */
+  char *header;					/* The resident portion of header */
+  char *section;				/* code+data+bss section */
+  long _fini;					/* Finalization */
+  dxe_handle_list *implicit_handle_list;	/* Linked list of implicitly open module by this module or NULL */
  } dxe_handle, *dxe_h;

  /* Last-resort symbol resolver */
  void *(*_dlsymresolver) (const char *symname) = NULL;
  /* Last-error unresolved symbol count */
@@ -110,10 +119,12 @@ void *dlopen(const char *filename, int m
    char *discardable;

    stk_node *node;
    static stk_node *stk_top = NULL;

+  dxe_handle_list *implicitly_open_handle_list;
+
  #ifndef __GNUC__
    static int cleanup = 0;
  #endif

    _dl_unresolved_count = 0;
@@ -180,11 +191,11 @@ found:

    /* Look through the loaded modules list */
    for (cur = dxe_chain; cur; cur = cur->next)
      if (!strcmp(realfn, cur->fname))
      {
-      cur->inuse++;
+      cur->in_use++;
        return cur;
      }

    fh = OPEN(filename, OPENFLAGS);
    if (fh < 0) return NULL;
@@ -202,13 +213,14 @@ found:
      return NULL;
    }

    /* O.k, fill the module handle structure */
    strcpy(dxe.fname, realfn);
-  dxe.inuse = 1;
+  dxe.in_use = 1;
    dxe.mode = mode;
    dxe.n_exp_syms = dxehdr.n_exp_syms;
+  dxe.implicit_handle_list = NULL;

    /* Read DXE tables and the data section */
    hdrsize = dxehdr.symbol_offset - sizeof(dxehdr);
    discardsize = dxehdr.dep_size + dxehdr.unres_size + dxehdr.nrelocs * sizeof(long);
    if ((dxe.header = malloc(hdrsize + dxehdr.sec_size)) == NULL)
@@ -240,11 +252,11 @@ found:
    /* Fill the unfilled portion of code+data+bss segment with zeros */
    memset(dxe.section + dxehdr.sec_f_size, 0, dxehdr.sec_size - dxehdr.sec_f_size);

    /* Load the dependencies */
    scan = discardable;
-  for (i = 0; i < dxehdr.n_deps; i++)
+  for (implicitly_open_handle_list = NULL, i = 0; i < dxehdr.n_deps; i++)
    {
      stk_node tmp;
      tmp.name = realfn;
      tmp.next = stk_top;
      stk_top = &tmp;
@@ -252,14 +264,35 @@ found:
      if (dlopen(scan, RTLD_GLOBAL) == NULL)
      {
        stk_top = tmp.next;
        goto unrecoverable;
      }
+    else
+    {
+      dxe_handle_list *next_handle_list;
+
+      stk_top = tmp.next;

-    stk_top = tmp.next;
+      scan = strchr(scan, 0) + 1;

-    scan = strchr(scan, 0) + 1;
+      /* Register all implicitly open modules by this one.  */
+      if ((next_handle_list = malloc(sizeof(dxe_handle_list))) == NULL)
+      {
+        errno = ENOMEM;
+        goto midwayerror;
+      }
+      next_handle->handle = dxe_chain;
+      next_handle->next = NULL;
+
+      if (implicitly_open_handle_list)
+      {
+        implicitly_open_handle_list->next = next_handle_list;
+        implicitly_open_handle_list = implicitly_open_handle_list->next;
+      }
+      else
+        dxe.implicit_handle_list = implicitly_open_handle_list = next_handle_list;
+    }
    }

    /* Allright, now we're ready to resolve all unresolved symbols */
    _dl_unresolved_count = dxehdr.n_unres_syms;
    _dl_unresolved_symbol[0] = 0;
@@ -325,10 +358,50 @@ found:
      errno = ENOMEM;
      goto midwayerror;
    }
    memcpy(dxe_chain, &dxe, sizeof(dxe_handle));

+#if defined(__DEBUG_DXE3__) && __DEBUG_DXE3__ == 1
+  {
+    FILE *f = fopen("c:/tmp/dxe_chain.txt", "a");
+
+    if (f)
+    {
+      fprintf(f, "dxe_chain                    : 0x%p\n"
+                 "  next                       : 0x%p\n"
+                 "  fname                      : %s\n"
+                 "  mode                       : %s\n"
+                 "  in_use                     : %d\n"
+                 "  n_exp_syms                 : %d\n"
+                 "  exp_table                  : 0x%p\n",
+                 dxe_chain, dxe_chain->next, dxe_chain->fname,
+                 dxe_chain->mode == RTLD_LAZY ? "RTLD_LAZY" :
+                 dxe_chain->mode == RTLD_NOW ? "RTLD_NOW" :
+                 dxe_chain->mode == RTLD_LOCAL ? "RTLD_LOCAL" :
+                 dxe_chain->mode == RTLD_GLOBAL ? "RTLD_GLOBAL" : "unknown",
+                 dxe_chain->in_use, dxe_chain->n_exp_syms, dxe_chain->exp_table);
+      for (i = 0; i < dxe_chain->n_exp_syms; i++)
+        fprintf(f, "    exp_table[%d]->offset     : %ld\n"
+                   "    exp_table[%d]->name       : %s\n",
+                   i, dxe_chain->exp_table[i]->offset, i, dxe_chain->exp_table[i]->name);
+      fprintf(f, "  header                     : 0x%p\n"
+                 "  section                    : 0x%p\n"
+                 "  _fini                      : %ld\n",
+                 dxe_chain->header, dxe_chain->section, dxe_chain->_fini);
+      if ((implicitly_open_handle_list = dxe_chain->implicit_handle_list))
+        for (; implicitly_open_handle_list; implicitly_open_handle_list = implicitly_open_handle_list->next)
+          fprintf(f, "  implicitly_open_handle_list: 0x%p\n"
+                     "    handle                   : 0x%p\n"
+                     "    handle->fname            : %s\n\n",
+                     implicitly_open_handle_list, implicitly_open_handle_list->handle, implicitly_open_handle_list->handle->fname);
+      else
+        fprintf(f, "  implicitly_open_handle_list: 0x00000000\n\n");
+      fclose(f);
+    }
+  }
+#endif
+
  #ifndef __GNUC__
    if (!cleanup)
    {
      cleanup = !0;
      atexit(_closeall);
@@ -348,11 +421,11 @@ midwayerror:
  int dlclose(void *dxe)
  {
    if (!dxe)
      return -1;

-  if (--((dxe_h)dxe)->inuse)
+  if (--((dxe_h)dxe)->in_use)
      return 0;

    /* finalization */
    if (((dxe_h)dxe)->_fini != -1)
      ((void (*) (void))(((dxe_h)dxe)->_fini + (long)((dxe_h)dxe)->section))();
@@ -361,10 +434,21 @@ int dlclose(void *dxe)
    {
      dxe_h *cur;
      for (cur = &dxe_chain; *cur; cur = &(*cur)->next)
        if (*cur == dxe)
        {
+        /* Un-register all implicitly loaded modules by this module.  */
+        dxe_handle_list *implicitly_open_handle_list = (*cur)->implicit_handle_list;
+        while (implicitly_open_handle_list)
+        {
+          dxe_handle_list *next_handle_list = implicitly_open_handle->next;
+
+          dlclose(implicitly_open_handle_list->handle);
+          free(implicitly_open_handle_list);
+          implicitly_open_handle_list = next_handle_list;
+        }
+
          *cur = ((dxe_h)dxe)->next;
          break;
        }
    }



- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019