I am wondering if there is a way to get Linux's PID (Process ID) from Common Lisp's REPL. That is, I would like to know the ID of the SBCL or Allegro process from the REPL of the process itself.
There's nothing in the Common Lisp specification that implements this. Process IDs are too implementation-dependent.
In SBCL, the SB-POSIX package provides Lisp interfaces to most POSIX system calls, so you would use (sb-posix:getpid).
In Allegro CL, operating system interface functions are in the EXCL.OSI package, so you would use (excl.ose:getpid)
There is a (basically) portable way to do this. CL provides for reading files and one can observe that the pid of the current process is in /proc/self/status (also /proc/self is a symlink to the process’ pid but I don’t think there’s a portable read link).
Specifically /proc/self/status is a text file and contains a line that looks like:
Pid: 439
So you could parse the file to extract that.
But then once you have the pid there isn’t much you can do with it without system calls or /proc weirdness
Final Solution (to the biggest part by #Dan Robertson's and #coredump - thank you guys!)
Actually #Dan Robertson gave the full answer - I realize in retrospect.
This answer is just the implementation of what he said. So give him the points!
(ql:quickload "CL-PPCRE") ;; for regex parsing
(defun get-this-pid ()
"Return PID of this current lisp process."
(with-open-file (in #P"/proc/self/status")
(loop for line = (read-line in nil)
while line
when (ppcre:scan "^Pid" line)
do (return (car
(ppcre:all-matches-as-strings "\\d+"
line))))))
;; to get current process id, call:
(get-this-pid) ;
;; returns for me at the moment using sbcl "12646"
;; this is correct as closing of all other sbcl processes
;; and doing "pidof sbcl" in the shell showed.
As #Don Robertson pointed out, the file /proc/self/status shows the program which opens it its "PID" number (every program sees it differently). Thank you Don, since this solves the problem of finding really the PID of the program (pidof sbcl in the shell would give several numbers if several lisp programs are running independently on the machine.
Calling external programs is obsolete, if we open this file then from within cl, like #coredump pointed out.
PID numbers of other programs
;; Thanks to #coredump - who suggested to use
;; `ppcre:split :whitespace-char-class` for capturing arbitrary numbers
;; in the answer string - I added a test for integer-string-p to clean
;; non-numberic values after split.
(ql:quickload "CL-PPCRE")
(defun integer-string-p (string)
"Does string constist only of '01234567890' characters?"
(reduce (lambda (x y) (and x y))
(mapcar (lambda (c) (member c (coerce "1234567890" 'list)))
(coerce string 'list))))
(defun extract-integers-from-string (s)
"Return integer-words of s."
(let ((l (ppcre:split :whitespace-char-class s)))
(remove-if-not #'integer-string-p l)))
(defun pid-numbers (program-name)
"Return PID numbers of a program in current machine."
(let ((pid-line (with-output-to-string (out)
(external-program:run "pidof" (list program-name)
:output out))))
(extract-integers-from-string pid-line)))
;; call it
(pid-numbers "sbcl")
(pid-numbers "firefox")
;; * (pid-numbers "sbcl")
;; ("16636" "12346")
;; * (pid-numbers "firefox")
;; ("24931" "19388" "19122" "10800" "10745") ; yeah I have many open :D
Related
I am trying to figure out Chicken Scheme's process procedure.
When I run it in the interpreter, this example code does what I expect (prints out "Hello, world!"):
(use posix)
(let-values (((in out pid) (process "echo \"Hello, world!\"")))
(print (read-line in)))
Based on this, my expectation is that if I echo \"Hello, world!\" with bc I should see the first line of bc's usual preamble:
bc 1.06
Instead, I get a blank line, and I don't get the interpreter's prompt back again until I hit Ctrl-C.
Or, sometimes I get this error:
thread is registered for I/O on unknown file-descriptor: 33 (expected 31)
[]
...more...
<syntax>
<syntax>
<syntax>
<syntax>
<syntax>
<syntax>
<syntax>
<syntax>
<syntax>
<syntax>
<syntax>
<eval>
<eval>
<eval>
<eval>
<eval> <--
and I get kicked back out to my shell prompt.
Additionally, how do I get the process I have started to respond to input? I expect the following to print 4, but instead get a blank line again:
(let-values (((in out pid) (process "bc")))
(begin
(display "2 + 2" out)
(print (read-line in))))
(How) can I use process to have an interactive dialog with a tool like bc?
There are several components to this question. The first you already figured out: bc will detect it's not running on a terminal so it won't print the banner.
The second is simple line buffering: In UNIX, simply printing to a port will not actually send out any data, unless you explicitly flush or send a newline. In CHICKEN, this can be done either by calling flush-output on the desired port, or appending a newline to the display call. I think bc will read until it sees a newline anyway, so flushing is not likely to help here. So either call newline on the port, or use (display "2 + 2\n" out) instead of (display "2 + 2" out).
The third is an actual bug: the error you get about an unexpected file descriptor. I've filed a bug report for that, thanks for pointing it out!
I am thinking to switch from vim + latex-vim module to emacs + evil + auctex,etc modules for editing latex files. I am completely new for emacs.
I have a lot of latex projects written for vim-latex with many files on different levels of a project directory.
In vim-latex the master file is defined by a file {master-file-name}.latexmain, e.g., if the main file is main.tex, then in the same directory there is main.tex.latexmain. I would like to have similar behavior in emacs (ideally accomplished with the emacs variable approach when it is necessarily, e.g., several master files in the same project directory).
Below you find the code for finding the name of the master file (it is my first elisp code, so any comments about how it can be ameliorated are very welcome)
(defun texmode-find-master-file ()
"Finds the master file for TeX/LaTeX project by searching for '{file-name}.latexmain' in the rood directories"
(let (foundFiles (currPath (expand-file-name "./")) result)
(while (and (not foundFiles) (not (equal currPath "/")) )
(setq foundFiles (directory-files currPath t ".*\.latexmain"))
(setq currPath (expand-file-name (concat currPath "../")))
)
(setq result (file-name-sans-extension (car foundFiles)))
(and (file-exists-p result) result)
)
)
However, I was not able to find where I can insert this code to modify the behavior of finding master files in AUCTeX. But may be there is a simpler or more beautiful way?
The related questions are
What should I modify in order to open (by means of find-file-at-point or similar) \input{tex/blabla2.tex} starting from the master path directory rather than the current directory? For example, I have three files: projdir/main.tex, projdir/tex/blabla1.tex, projdir/tex/blabla2.tex; and if I am editing blabla2.tex and there is \input{tex/blabla1.tex} how can I open this file?
How to force AUCTeX to define the same type of document as it is in the master file, e.g., if the main file type is 'latex', then all the files in the same project directory are also 'latex' (if not specified explicitly), not 'tex' as it is defined for some of files in my current settings.
I have finally found some answers. The code below solves some questions (can be put in .emacs files). We change also default directory in order to force find-file-at-point (ffap) to find the file starting from the master-file directory.
It seems that there is a bit strange behavior for ffap function. When there are files dir/part-I.tex and dir/part-II.tex and an input like \input{dir/part-I}, function ffap does not want to find dir/part-I.tex, while with \input{dir/part-II} it works just fine. But it is not a big issue.
Finally, I still do not know how to select the file type based on the type of the master file...
(defun TeX-find-master-file ()
"Finds the master file for TeX/LaTeX project
by searching for '{file-name}.latexmain' in the good directories"
(let (foundFiles (currPath (expand-file-name "./")) foundFile)
(while (and (not foundFiles) (not (equal currPath "/")) )
(setq foundFiles (directory-files currPath t ".*\.latexmain"))
(setq currPath (expand-file-name (concat currPath "../"))))
(and
(setq foundFile (car foundFiles))
; removing .latexmain extension
(setq foundFile (file-name-sans-extension foundFile))
(file-exists-p foundFile)
foundFile)))
(defun TeX-set-master-file (&optional ignore1 ignore2 ignore3)
"Finds the master file by means of TeX-find-master-file
and set TeX-master to it value"
(setq TeX-master (or (TeX-find-master-file) TeX-master)))
;Finally we change the func TeX-master-file from AUCTeX
; in order to first apply the logic with *.latexmain
; and only then to apply the standard logic of AUCTeX
(advice-add 'TeX-master-file :before #'TeX-set-master-file)
For ffap working in latex mode from master-dir file we the following command:
(advice-add 'ffap-latex-mode :before-until #'(lambda (name)
(ffap-locate-file name
'(".cls" ".sty" ".tex" "")
(cons (file-name-directory TeX-master)
'()))))
Maybe I'm just missing something obvious in the System.Process API (http://hackage.haskell.org/package/process), but it doesn't appear to support getting the raw PID of a process created. The API usually returns a ProcessHandle which can be used easily enough, but this doesn't appear to fulfill a deployment need I have.
I have a case where I want to spawn a long-running process, log the PID it's using, and be able to automatically come back at a later time (days, weeks, months) and kill the old process and re-start with a new process. I'm sure there are several ways to do this auto-deploy-and-restart, but PIDs seemed like the simplest way to do so without too much platform-dependent code.
I'm open to other suggestions about my underlying problem, but it seems odd to me that I can't find any direct PID references (or a way to convert to them) in the process API. This seems like an oversight of the API.
Here is some example code:
import System.Process
import System.Process.Internals
-- | returns Just pid or Nothing if process has already exited
getPid ph = withProcessHandle ph go
where
go ph_ = case ph_ of
OpenHandle x -> return $ Just x
ClosedHandle _ -> return Nothing
main = do
(_,_,_,ph) <- createProcess $ shell "echo $$"
getPid ph >>= print
Note: I haven't tested this under Windows, but it works on OSX and, presumably, Linux.
For Windows, the Win32 package has a getProcessId function in the module System.Win32.Process, and according to code I've read, this should work:
import System.Win32.Process (getProcessId)
main = do
(_,_,_,ph) <- createProcess $ shell "echo $$"
pid <- withProcessHandle ph go
print pid
where go (OpenHandle x) = fmap Just $ getProcessId x
go (ClosedHandle _) = return Nothing
The code I am basing this on is the code for interruptProcessGroupOf (link)
Looks like interruptProcessGroupOf in System.Process calls either System.Posix.Process.getProcessGroupIDOf (POSIX/not Windows) or System.Win32.Process.getProcessId (Windows) to get the pid: http://git.haskell.org/packages/process.git/blob/HEAD:/System/Process.hs
If everything else fails,
import System.Process.Internals
and then dig inside the ProcessHandle abstraction. You probably want to extract the PHANDLE from the MVar.
Note that this breaks the abstraction layer, which is meant to make the code portable across OSs. Use it with extreme care, and be prepared for it to break in new versions of the library.
I'm using Clozure CL to write an app. In the app, I need to write several files, so I made a read-write-lock for each file.
Now I'm trying to write a quit function. It checks whether all the file writings are complete and then quit. Basically it works like below:
Grab all the files read-write-locks
Quit CCL
I read the Clozure CL document, but can't find any function like grab-write-lock. I can only find "grab-lock", "with-read-lock" and "with-write-lock". 'grab-lock' won't work on read-write-lock, the other two will release the lock automatically. So how can I grab all the file read-write-locks (not release them) and quit the app?
I'm not all that familiar with Clozure CL's locking mechanisms, but I think that some macroexpansion can illustrate at least one way to do this:
CL-USER> (pprint (macroexpand-1 '(with-write-lock (my-lock)
do-something)))
(CCL::WITH-LOCK-CONTEXT
(LET* ((#:G350 (MAKE-LOCK-ACQUISITION))
(#:G351 MY-LOCK))
(DECLARE (DYNAMIC-EXTENT #:G350))
(UNWIND-PROTECT
(PROGN
(CCL::WRITE-LOCK-RWLOCK #:G351 #:G350)
DO-SOMETHING)
(WHEN (CCL::LOCK-ACQUISITION.STATUS #:G350)
(CCL::UNLOCK-RWLOCK #:G351)))))
I can't say whether this (using ccl::with-lock-context/ccl::write-lock-rwlock) is a good way to do this in your own code or not, but it's certainly a way to do it.
I'm not sure I understand what "unshifting a path" with -I means in expresso. Does that mean if I run expresso with the switch as such
expresso -I myCode test/*
That when I normally use require statements in my tests in my test folder such as
models = require "../myCode/models"
That instead I can call the require like this?
models = require "models"
I thought that was my understanding but it doesn't seem to work as it gives me an "Error, cannot find module"
Overview
Unshift basically just means "add an item to the beginning of a sequence of items".
So in this context, unshifting a path just means to add a path to the beginning of the sequence of paths.
The following cheatsheet explains a little more using arrays as an example.
Quick Cheatsheet:
The terms shift/unshift and push/pop can be a bit confusing, at least to folks who may not be familiar with programming in C.
If you are not familiar with the lingo, here is a quick translation of alternate terms, which may be easier to remember:
* array_unshift() - (aka Prepend ;; InsertBefore ;; InsertAtBegin )
* array_shift() - (aka UnPrepend ;; RemoveBefore ;; RemoveFromBegin )
* array_push() - (aka Append ;; InsertAfter ;; ;; InsertAtEnd )
* array_pop() - (aka UnAppend ;; RemoveAfter ;; ;; RemoveFromEnd )