From: Bulent M. <bm...@ac...> - 2006-06-25 23:23:28
|
This 'how do I make a single executable' question is just about ready to come up in the Turkish lisp group's mailing list, so I looked into it. It seems to work OK under linux using save-lisp-and-die but I have several questions: -- 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 |
From: Nikodemus S. <nik...@ra...> - 2006-06-26 10:43:44
|
Bulent Murtezaoglu <bm...@ac...> writes: > -- 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." |
From: Bulent M. <bm...@ac...> - 2006-06-26 12:48:52
|
>>>>> "NS" == Nikodemus Siivola <nik...@ra...> writes: [...] >> 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? 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 |
From: Nikodemus S. <nik...@ra...> - 2006-06-26 13:55:28
|
Bulent Murtezaoglu <bm...@ac...> writes: > 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." |