Euphoria Ticket #968: read_file fails to read /proc/<pid>/cmdline on Linux

Tested on

   Euphoria Interpreter v4.1.0 development 
   64-bit Linux, Using System Memory 
   Revision Date: 2015-02-02 14:18:53, Id: 5861:57179171dbed 

cat /proc/1713/cmdline shows command line of pid 1713

$ cat /proc/1713/cmdline 
/usr/lib/kde4/libexec/kaccessibleapp$ 

read_file returns an empty sequence

printf(1, "[%d] %s\n", {i, sprint(s)}) 
name = read_file("/proc/" & s[D_NAME] & "/cmdline") 
printf(1, "  %s: %s\n", {"/proc/" & s[D_NAME] & "/cmdline", sprint(name)}) 
 

[214] {{49,55,49,51},{100},0,2017,8,24,7,39,56,0,0} 
  /proc/1713/cmdline: {} 

Jean-Marc

Details

Type: Bug Report Severity: Normal Category: Language
Assigned To: unknown Status: Won't Fix Reported Release: 5861:57179171dbed
Fixed in SVN #: View VCS: none Milestone:

1. Comment by jmduro Aug 24, 2017

read_lines does the job where read_file fails:

  /proc/1713/cmdline: {{47,117,115,114,47,108,105,98,47,107,100,101,52,47,108,105,98,101,120,101,99,47,107,97,99,99,101,115,115,105,98,108,101,97,112,112,0}} 

2. Comment by jimcbrown Aug 24, 2017

This one is pretty straight-forward.

read_file() relies on seek(-1) to figure out the length of the file. However, procfs doesn't appear to support this. procfs is an unusual case. du and ls also report that /proc/1/cmdline is 0 bytes, and file reports that it is an empty file.

This is described better here: https://unix.stackexchange.com/questions/282701/why-some-shells-read-builtin-fail-to-read-the-whole-line-from-file-in-proc

I don't think it's worth bothering to fix read_file() to handle this unusual case, but it may make sense to have some alternative function that just does flatten(read_lines()) or something. If we really did want to fix read_file(), we could modify it so that if the seek(-1) reports a length of zero or less, then ignore it and just use a while loop to read data until EOF is hit. (This, incidently, is how read_lines() works and thus the reason that it is able to read data from those files.)

3. Comment by jmduro Aug 24, 2017

OK Jim,

Here is how I get my process IDs:

without warning 
include std/error.e 
include std/filesys.e 
include std/os.e 
include std/text.e 
include std/convert.e 
include std/search.e 
include std/io.e 
include lib/_types_.e 
include lib/_debug_.e 
include lib/_file_.e 
include lib/_sequence_.e 
include lib/_conv_.e 
 
------------------------------------------------------------------------------ 
 
function get_process_id(sequence processname) 
-- Returns pids of processname instances 
  object   x 
  sequence processes = {}, s, name 
  integer fn, c, ownPID 
 
  x = dir("/proc/*") 
  ownPID = get_pid() 
  if sequence(x) then           -- Exclude forbidden DIRs 
    for i = 1 to length(x) do   -- Loop through DIR content 
      s = x[i] 
      if find('d',s[D_ATTRIBUTES]) and 
         not (equal(s[D_NAME],".") or equal(s[D_NAME],"..")) then  -- Check for SubDIRs 
        if is_integer(s[D_NAME]) and (ownPID != to_number(s[D_NAME])) then 
          fn = open("/proc/" & s[D_NAME] & "/cmdline", "rb") 
          name = "" 
          c = getc(fn) 
          while (c != EOF) do 
            if c then name &= c end if  -- remove NULL 
            c = getc(fn) 
          end while 
          close(fn) 
          if sequence(name) and length(name) then 
            if match(processname, name) then 
              processes = append(processes, s[D_NAME]) 
            end if 
          end if 
        end if 
      end if 
    end for 
  end if 
  return processes 
end function 
 
------------------------------------------------------------------------------ 
 
function is_running(sequence processname) 
-- Returns true if at least one instance of processname is running 
  sequence processes 
   
  processes = get_process_id(processname) 
  return length(processes) > 0 
end function 
 
------------------------------------------------------------------------------ 
 
  sequence processname 
   
  sequence cmd = command_line() 
  if length(cmd)< 3 then 
    puts(1, "Syntax: is_running process_cmdline\n") 
    abort(1) 
  end if 
 
  processname = cmd[3] 
  puts(1, "processname: '" & processname & "'\n") 
  if length(processname)>0 then 
    if is_running(processname) then 
      puts(1, "Process " & processname & " is running\n") 
    else 
      puts(1, "No process " & processname & " found\n") 
    end if 
  end if 

Search



Quick Links

User menu

Not signed in.

Misc Menu