> On 15 Aug 2016, at 15:07, Faré <fah...@gmail.com> wrote:
> 
>>  
>> https://gitlab.common-lisp.net/epipping/asdf/commit/ffd8d8564bdc6551f2b682e7683bf16d6d459161
>> 
>> (to be squashed into an earlier commit) that I’m rather happy with.
>> 
> Uh, your comment suggests that on lispworks6, your destructuring-bind is 
> wrong.

Oh, the comment may be doing more harm than good then. The code is actually 
correct. It’s just that
in the if-branch, lispworks 6 will return (io,err,pid), and in the else-branch 
(pid), whereas lispworks7 will
return (io,err,pid) in both branches.

> Note that I'm OK with declaring we don't support lispworks6 anymore,
> but that must be made explicit. Also, ask Robert what he thinks about it.

I don’t think this will be necessary. I haven’t been able to test with 
lispworks 5 but lispworks 6 works
pretty well.

>>> * Also, is #+lispworks7 future-proof? Is there a feature for 7-or-later?
>> 
>> I don’t think so, no. It seems that each version has a feature corresponding 
>> to its own version but not others. We could maybe provide our own, though. 
>> We cannot know what versioning scheme they’ll use in the future but it 
>> shouldn’t be too difficult to find out what features lispworks has defined 
>> in the past. So a
>> 
>>  (lispworks7-or-greater-p)
>> 
>> could probably be implemented as
>> 
>>  (not (or #+(or lispworks4 lispworks5 lispworks6) t))
>> 
>> or something along those lines.
>> 
> Yuck. I'd rather query SYSTEM::*MAJOR-VERSION-NUMBER* in a #..

I didn’t know about that variable. The resulting code would be nicer but it’s 
still a private symbol which might disappear in the future. Personally, I’d 
prefer to go with the uglier but more official version.

>> (A) The first is with the :overwrite default for :if-output-exists. [...]
>> So since all [implementations] appear to support the behaviour of :supersede 
>> (even though not necessarily by that name) and not all of them support 
>> :overwrite, it might make sense to change the default from :overwrite to 
>> :supersede and then (like other normaliser functions) have a translator that 
>> turns :supersede into :overwrite for CLISP. This would unfortunately also 
>> affect the (exported) run-program function. On the plus side, it would only 
>> change behaviour that previously could not be relied upon anyway.
>> 
> Yes, that would be the Right Thing(tm).
> The entire purpose of UIOP is to provide some portable abstractions
> with stable semantics abstracting over implementation specifics,
> rather than functions the meaning of which is actually not portable.
> See my ASDF3 essay on this topic.
> 
>> (B) Process termination
>> 
>> Even though it’s possible to kill a process on nearly ever platform somehow 
>> (not on CLISP, except for processes spawned through ext::launch) there are 
>> multiple tiers of support for that: From native to external: If you have a 
>> process in MKCL, you can terminate it through its process object, on unix or 
>> windows. That’s the ideal situation.
>> 
> If it helps with CLISP, maybe ext::launch should be the default on CLISP.
> I admit I don't care too much about CLISP, that hasn't been actively
> maintained for years.
> (It still ships with ASDF 2.33, for John McCarthy's sake.)

It appears there are some attempts to breathe new life into CLISP, though. See 
e.g.

  https://sourceforge.net/u/musteresel/clisp/

>> The worst-possible situation that can still be handled if needed is when all 
>> you have is the PID: you end up calling `taskkill` on windows, through 
>> cmd.exe, or `kill` on unix, through the shell. I only recently started 
>> thinking about potential issues that this might involve other than 
>> performance, not only in this extreme case but also in cases that lie 
>> half-way between the MKCL situation and the worst-possible scenario, e.g. 
>> SBCL’s.
>> 
>> If you obtain the PID of an arbitrary external process and then try to kill 
>> it through that PID at a later point in time, the process may no longer be 
>> running. It may not even exist anymore. Worse yet, its PID may have been 
>> recycled by the system and assigned to a newly spawned process that you end 
>> up killing by accident!
>> 
> Note that on Unix, the race condition between killing a process
> and the process dying then its PID being recycled is inherent,
> whatever abstraction MKCL may try to provide that SBCL doesn’t.

Yes, but we’re not dealing with this general problem as I tried to outline in 
the paragraph after that (quoting myself):

  Fortunately, I am not trying to solve this general problem but the simpler 
problem of killing a process spawned through run-program, which will 
necessarily be a child process. Such a process will signal its parent with 
SIGCHLD when it terminates and stick around as a zombie until it is waited for.

So the issue is solvable here, no?

> The only mitigating behavior would be for the kernel to insert a pause
> before a PID could be used, and hope that programs never try kill a PID
> more than that pause duration after having checked the process was alive
> (and even then, if the process is kill -STOP'ped between the check and the 
> kill,
> there's nothing that can prevent the race condition).
> Of course, 16-bit PIDs make the situation particularly tight on Unix
> 
>> ((B') I’m not sure what the best way to handle this requirement of reaping 
>> is. %wait-process-result currently calls both functions, so it would be 
>> possible to require that asynchronously spawned processes are waited on at 
>> some point, mirroring to some extent the requirement that every C program 
>> that calls fork() should call wait() at some point. So the name would be 
>> rather appropriate even.)
>> 
> Yes, it is fair to require that asynchronous UIOP:RUN-PROGRAM users
> should always call wait-process (or whatever you call the API
> function) and not rely on the implementation doing it for them.

Okay, great.


Elias


Reply via email to