-- The manual is accurate in that save-lisp-and-die does not work if
multiple threads are running. It dies alright, but it also creates a
zero length file while doing so. Is there a good reason other than
lack of developer interest/time for not having it detect if more than
one thread is running and refuse to do anything?
Going by the fork suggestion in the manual, I came up with something
like what's below:
(defun make-standalone-exe (file-name start-function)
(let ((pid (sb-posix:fork)))
(cond ((= 0 pid)
(sb-ext:save-lisp-and-die file-name
:toplevel #'(lambda ()
(funcall start-function)
(sb-ext:quit))
:executable t))
(t (sb-posix:waitpid pid 0)))))
While this does work OK for dumping hello world and such from an sbcl
running under slime, I don't understand what forking an sbcl with
multiple running threads does and in what way the image might be
broken. I figured the manual's suggestion was serious and tried it.
If this is indeed kosher perhaps a better version of something like
the above could enter the manual as an example? (Details for getting
the child process to output into the slime repl buffer rather than the
inferior lisp one probably doesn't belong in the sbcl manual, but if
it can be done from the swank/sbcl-side, I'd be happy to find out
how).
-- Would it be a good idea to add something more concrete to the
explanation for the :executable key for sb-ext:save-lisp-and-die? It
could say something like:
":executable If true, arrange to combine the sbcl runtime and the core
image to create a standalone executable. If false (the default), the
core image will not be executable on its own. If a standalone executable
is being created sb-ext:quit should be called before exiting lisp
entirely."
The last sentence could probably also be added to the explanation for
:toplevel. It could also be that I'm missing something and there are
other ways of exiting normally. If so, what are they? What should I
tell people, if asked?
-- Does it make sense for there to be any command line processing for
sbcl's own switches in a standalone executable? I started thinking
about this issue when I realized I needed to call my test executable
with --noinform to stop the start-up banner from getting printed.
Regardless of what the right thing turns out to be for the switch
issue, the banner issue remains. There does not seem to be any way
(short of editing runtime.c and rebuilding) to turn off the printing
of the banner in the dumped executable w/o using that command-line
switch. Perhaps something as simple as not calling print_banner() if
the exectuable is standalone would work OK?
Thanks.
cheers,
BM
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Sbcl-help mailing list
Sbcl...@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sbcl-help
> -- The manual is accurate in that save-lisp-and-die does not work if
> multiple threads are running. It dies alright, but it also creates a
> zero length file while doing so. Is there a good reason other than
> lack of developer interest/time for not having it detect if more than
> one thread is running and refuse to do anything?
More like no-one thought of it before. ,-)
Seems simple enough to do, and a nice idea. While save-lisp-and-die
isn't ment for saving state, some people do use it for that -- so
signaling an error instead of losing data is a decent thing to do.
> While this does work OK for dumping hello world and such from an sbcl
> running under slime, I don't understand what forking an sbcl with
> multiple running threads does and in what way the image might be
> broken.
I belive fork() duplicates only the thread it is being called from,
which may create problems in the child SBCL, as it knows about the
other threads that were running, but are now missing -- except that
the thread-id provided by the OS points to a running thread in another
process.
But possibly this situation is sufficiently similar to having dead
threads that the GC will handle it sanely?
fork() should be fine even in multithreaded environment if you are
going to live in foreign code from that point on -- I'd only expect
trouble at next GC (or PURIFY).
This whole mess is probably fixable by creating appropriate
pthread_atfork() handlers for each thread started by SBCL, or
making the GC deal with the pre-fork leftovers.
> I figured the manual's suggestion was serious and tried it. If this
> is indeed kosher perhaps a better version of something like the
> above could enter the manual as an example?
Aside from the issue that threads are liable to be a problem with
fork() too, I don't see why not.
> (Details for getting the child process to output into the slime repl
> buffer rather than the inferior lisp one probably doesn't belong in
> the sbcl manual, but if it can be done from the swank/sbcl-side, I'd
> be happy to find out how).
I would expect judicious use of INSPECT to point to way.
(*STANDARD-OUTPUT* in child vs. *STANDARD-OUTPUT* in parent.)
> -- Would it be a good idea to add something more concrete to the
> explanation for the :executable key for sb-ext:save-lisp-and-die? It
> could say something like:
>
> ":executable If true, arrange to combine the sbcl runtime and the core
> image to create a standalone executable. If false (the default), the
> core image will not be executable on its own. If a standalone executable
> is being created sb-ext:quit should be called before exiting lisp
> entirely."
>
> The last sentence could probably also be added to the explanation for
> :toplevel. It could also be that I'm missing something and there are
> other ways of exiting normally. If so, what are they? What should I
> tell people, if asked?
Calling exit() in foreign code, for example.
On the other paw, I'd personally prefer to automatically QUIT with
return code of 0 if the toplevel function returns.
> -- Does it make sense for there to be any command line processing for
> sbcl's own switches in a standalone executable? I started thinking
> about this issue when I realized I needed to call my test executable
> with --noinform to stop the start-up banner from getting printed.
> Regardless of what the right thing turns out to be for the switch
> issue, the banner issue remains. There does not seem to be any way
> (short of editing runtime.c and rebuilding) to turn off the printing
> of the banner in the dumped executable w/o using that command-line
> switch. Perhaps something as simple as not calling print_banner() if
> the exectuable is standalone would work OK?
This has been talked about.
My personal favorite is to move as --noinform processing out of the
runtime onto lisp-land, so that the inform-messages could be
customized (including motd-like things) or suppressed entirely by
saving a core with the appropriate hooks.
I also suspect that using --sbcl-version and --sbcl-core, instead of
--version and --core as commandline arguments for executable cores
would be a good idea.
Surely
$ frobniz --version
should return the version of frobniz, not the SBCL it was built on!
Cheers,
-- Nikodemus Schemer: "Buddha is small, clean, and serious."
Lispnik: "Buddha is big, has hairy armpits, and laughs."
NS> Aside from the issue that threads are liable to be a problem
NS> with fork() too, I don't see why not.
At least as far saving 'hello world' goes, the fork scheme does work
from an sbcl with multiple threads running. But I don't think that
says much (thanks for the other info).
>> ... It could also be that I'm missing
>> something and there are other ways of exiting normally. If so,
>> what are they? What should I tell people, if asked?
NS> Calling exit() in foreign code, for example.
Hah, there you go. Thanks. Still I'd feel more comfortable telling
relative newbies to RTFM if the manual said something more concrete
than that the toplevel function should not return. My suggested
verbiage wouldn't work, but maybe a short (eg. it could call
sb-ext:quit) with the parantheses would?
NS> On the other paw, I'd personally prefer to automatically QUIT
NS> with return code of 0 if the toplevel function returns.
That would be in-line with my intuitions too.
[...]
NS> This has been talked about.
Where do I look for that conversation? Google found this:
http://www.archivesat.com/Steel_Bank_Common_Lisp_(SBCL)/thread648967.htm
but I already know that part.
NS> My personal favorite is to move as --noinform processing out
NS> of the runtime onto lisp-land, so that the inform-messages
NS> could be customized (including motd-like things) or suppressed
NS> entirely by saving a core with the appropriate hooks.
At the very least, yes. I haven't checked for this, so it may already
be happenning but just in case it isn't --no-sysinit --no-userinit
should also be assumed for standalone executables. (Either way,
perhaps this should also be clarified in the save-lisp-and-die section
of the manual?).
NS> I also suspect that using --sbcl-version and --sbcl-core,
NS> instead of --version and --core as commandline arguments for
NS> executable cores would be a good idea.
NS> Surely
NS> $ frobniz --version
NS> should return the version of frobniz, not the SBCL it was
NS> built on!
Yes, but coding two sets of switches just to handle
$ frobniz --sbcl-version
does not make much sense to me. If the frobniz author cared about
this he could code it himself. If he doesn't care, then the forbniz
users are probably best left wondering just how on earth a handful
of people coded a 30 meg executable in C.
Anyway one also expects
$ sbcl --version
to work.
It seems reasonable to me that standalone executables get/process the
entire command-line themselves, but I am just shooting from the hip
as I don't yet know what the issues are.
cheers,
BM
> Where do I look for that conversation? Google found this:
>
> http://www.archivesat.com/Steel_Bank_Common_Lisp_(SBCL)/thread648967.htm
>
> but I already know that part.
I'm pretty sure there is something more in the bowels of sbcl-devel,
but possibly I am mistaken. Maybe #lisp archives?
> At the very least, yes. I haven't checked for this, so it may already
> be happenning but just in case it isn't --no-sysinit --no-userinit
> should also be assumed for standalone executables. (Either way,
> perhaps this should also be clarified in the save-lisp-and-die section
> of the manual?).
The parsing of lisp-side init-options is done by the default :toplevel
function, so yes, if you replace that, then normal init-files aren't
processed anymore.
...but clarification of this in the manual is probably in order.
> NS> Surely
>
> NS> $ frobniz --version
>
> NS> should return the version of frobniz, not the SBCL it was
> NS> built on!
>
> Yes, but coding two sets of switches just to handle
>
> $ frobniz --sbcl-version
>
> does not make much sense to me. If the frobniz author cared about
> this he could code it himself. If he doesn't care, then the forbniz
> users are probably best left wondering just how on earth a handful
> of people coded a 30 meg executable in C.
Well, all it takes is to automagically prefix the switches with "sbcl"
when running with an embedded core, and the benefit is mostly for
SBCL developers who then have an easy way to check which version of
SBCL something was built with.
Now that I think of it, I think I'd also like to have --sbcl-toplevel
option to force entry into the default :toplevel function instead of
the one the core was saved with -- which should be quite useful for
debugging delivery problems.
> Anyway one also expects
>
> $ sbcl --version
>
> to work.
Right. I ment to keep that and require the prefix only when using
an embedded core.
> It seems reasonable to me that standalone executables get/process the
> entire command-line themselves, but I am just shooting from the hip
> as I don't yet know what the issues are.
Mostly yes. But I'd personally be loath to make the normal runtime
arguments inaccessible.
Cheers,
-- Nikodemus Schemer: "Buddha is small, clean, and serious."
Lispnik: "Buddha is big, has hairy armpits, and laughs."