On Wed, Mar 24, 2021 at 9:18 AM Matias N. <mat...@imap.cc> wrote:

>
>
> On Tue, Mar 23, 2021, at 22:09, Nathan Hartman wrote:
> > On Tue, Mar 23, 2021 at 8:39 PM Matias N. <mat...@imap.cc <mailto:
> matias%40imap.cc>> wrote:
> >
> > > Hi,
> > > while using getopt() from a task started from NSH I realized subsequent
> > > calls reused the global optind and similar variables resulting in
> different
> > > results each time. I'm aware this is expected in FLAT mode and is
> related
> > > to the issue of static C++ constructors (they would only be called
> once,
> > > not every time the task is started).
> > >
> > > What I wonder is what could we do to avoid this common pitfall:
> > > - document it somewhere (a common issues/troubleshooting section in the
> > > docs would be good to have anyways) and just accept the issue
>

Wiki already mention this issue here:
https://cwiki.apache.org/confluence/display/NUTTX/Linux+Processes+vs+NuttX+Tasks
Greg shares many knowledge in wiki. To improve the visibility, it's better
to migrate Confluence to Documentation.

> > - religiously initialize globals myself before being used (a pain, error
> > > prone, and a bit adhoc, working only for FLAT mode)
>
> > - support reentrant versions of all possible APIs and always use these
> in FLAT mode


Yes, it's the right direction to promote the reentrant API.


> > > - devise a mechanism to mimic what would be done by OS in KERNEL mode
> (add
>
> > some custom handler to APIs internally using globals, such as getopt,
> that can be
>
> > called either manually by user or by the OS itself when the task is
> started?)


The custom handler isn't enough here, because the real problem is we need
the global variables per task/process.
As Greg suggests, we need something like TLS but per task/process not per
thread(e.g. task_getspecific/task_setspecific).
Once the mechanism is done, getopt can be converted to confirm the standard
trivally.


>
> > - other?


The transparent/standard solution is switched to the ELF binary(note: it
doesn't depend on KERNEL mode), and then loses the XIP benefit(huge memory
penalty). But, it's doable to XIP again by combining ELF loader and ROMFS.


> >
> >
> > When using globals, best practice is to make it really clear that the
> > variables are global. Many programmers do this by prefixing global
> variable
> > names with g_*.
> >
> > I take a different approach: A long time ago, I started grouping all
> > globals in a struct, which has one global instance called Global. It
> makes
> > it easy to find all globals, and furthermore at the start of the program
> as
> > a matter of policy the first thing I do is memset() the Global struct to
> 0.
> > Yes, I know that is often redundant to the startup code, but in some
> > situations the startup code doesn't initialize globals. The FLAT model is
> > one example of this (from the 2nd invocation onwards). I've seen other
> > examples of this over the years. By memset()ing your globals at the start
> > of main() you can rest assured that the globals are in fact zeroed,
> > regardless of whatever else happened before main(). It has another side
> > benefit: with globals grouped this way, it becomes trivial to take a
> > standalone program and turn it into a component of a larger program.
> > tl;dr, this
> > approach has worked great for me for a long time.
>
> That sounds like a good approach.
>
> >
> > Caveat: It won't help if your program (or any API called by it) uses
> > globals that are outside your control, and therefore, not initialized by
> > you. :-/
>
> Yes, my concern is about functions such as getopt(). If you just follow the
> description of the API and use it as normal you reach this pitfall. I was
> looking
> for some approach to avoid this as much as possible. For getopt() I see
> there's
> even no standard getopt_r(), so we would have to provide our own, which
> may not
> be a bad idea.
> Still, this issue will probably present in many other places.
>
>
Seldom people will call getopt_r in Linux, because the different process
gets the new and clean copy, but it is crucial for NuttX to work correctly.
Yes, getopt_r isn't standardized by committee, but it follows the
convention used by other similar functions(e.g. strtok_r) and implemented
by glibc.

>
> > Nathan
> >
>
> Best,
> Matias

Reply via email to