Opened 8 years ago

Last modified 3 months ago

#1487 new bug

unix package: test needed for getLoginName

Reported by: simonmar Owned by: ekmett
Priority: lowest Milestone:
Component: Core Libraries Version:
Keywords: Cc: adrien@…, core-libraries-committee@…
Operating System: Linux Architecture: Unknown/Multiple
Type of failure: Incorrect result at runtime Test Case:
Blocked By: Blocking:
Related Tickets: #8293 Differential Revisions:

Description

I disabled the test for getLoginName in unix/tests/user001 because getLoginName cannot be called unless stdin is a terminal, which it isn't during an unattended build. Perhaps we can test this by setting up a pseudoterminal first, but that requires the pty patches which aren't in yet.

Attachments (1)

0001-Enable-test-for-getLoginName.patch (3.1 KB) - added by thomie 11 months ago.

Download all attachments as: .zip

Change History (29)

comment:1 Changed 8 years ago by igloo

  • Milestone changed from 6.8 branch to Not GHC

comment:2 Changed 7 years ago by simonmar

  • Architecture changed from Unknown to Unknown/Multiple

comment:3 Changed 7 years ago by simonmar

  • Operating System changed from Unknown to Unknown/Multiple

comment:4 Changed 6 years ago by simonmar

  • difficulty changed from Easy (1 hr) to Easy (less than 1 hour)

comment:5 Changed 4 years ago by igloo

  • Milestone changed from Not GHC to 7.4.1
  • Type of failure set to None/Unknown

comment:6 Changed 3 years ago by igloo

  • Milestone changed from 7.4.1 to 7.6.1
  • Priority changed from low to lowest

comment:7 Changed 3 years ago by adrien

Hello,

What are the pty patches? are they in now? If not, is there a related ticket that needs to be solved first?

comment:8 Changed 3 years ago by adrien

  • Cc adrien@… added
  • Owner set to adrien

comment:9 Changed 3 years ago by simonmar

The pty patches have been in for some time.

comment:10 Changed 3 years ago by adrien

Thank you. I realize now I should have read the commit logs of the unix lib before naively asking, I may have found the answer there.

It can take me some time to fix this, as I need to become familiar with the code and the workflow, but I think this is a good place to start.

comment:11 Changed 3 years ago by igloo

  • Milestone changed from 7.6.1 to 7.6.2

comment:12 Changed 2 years ago by adrien

Hello,

Strangely, the issue doesn't seem to occur anymore. I am using ghc 7.7.20121207 on Arch Linux 64 bits (cloned it today).

After uncommenting the line for getLoginName, I:

  • loaded it in ghci, and run main: ok
  • compiled user001.hs and run it locally: ok
  • ran the testsuite without modifying user001.stdout, to check I edited the right file: got a difference with user001.stdout, what I expected
  • added the line 'getLoginName: OK' after getGroups, ran the test suite: ok

I did the same for getUserEntryForName, no error.

I cannot reproduce the bug. Is there another to test it, or shall we conclude that the bug disappeared?

Kind regards,
Adrien

comment:13 Changed 2 years ago by igloo

It still fails for me:

$ make CLEANUP=1 TEST=user001
[...]
=====> user001(normal) 5 of 28 [0, 0, 0]
cd . && '/home/ian/ghc/git/ghc/inplace/bin/ghc-stage2' -fforce-recomp -dcore-lint -dcmm-lint -dno-debug-output -no-user-package-db -rtsopts -fno-ghci-history -o user001 user001.hs  -package unix  >user001.comp.stderr 2>&1
cd . && ./user001    </dev/null >user001.run.stdout 2>user001.run.stderr
Actual stdout output differs from expected:
--- ./user001.stdout    2011-04-01 14:32:07.000000000 +0100
+++ ./user001.run.stdout        2012-12-08 17:05:06.000000000 +0000
@@ -3,6 +3,7 @@
 getEffectiveUserID: OK
 getEffectiveGroupID: OK
 getGroups: OK
+getLoginName: ERROR: getLoginName: illegal operation (Inappropriate ioctl for device)
 getEffectiveUserName: OK
 getGroupEntryForID: OK
 getGroupEntryForName: OK
*** unexpected failure for user001(normal)
[...]

comment:14 Changed 2 years ago by adrien

Thanks for the feedback.

It eludes me why it works on my linux and not yours. On which platform did you run the test? I can install it in a virtual machine and see if I can reproduce it. I am not of great help if I can't reproduce it.

I could then try to use getlogin_r, maybe the problem is in the code and not in the test. Or strace the test and get more info on the error.

comment:15 Changed 2 years ago by igloo

I used Debian amd64/Linux.

comment:16 Changed 2 years ago by adrien

Thanks. I installed Debian 6.0.6 amd64 in a virtual machine and I can reproduce it.

comment:17 Changed 2 years ago by morabbin

  • Operating System changed from Unknown/Multiple to Linux
  • Type of failure changed from None/Unknown to Incorrect result at runtime

comment:18 Changed 11 months ago by thomie

  • Owner changed from adrien to thomie

Changed 11 months ago by thomie

comment:19 Changed 11 months ago by thomie

The attached patch fixes this issue.

I tried going the pseudo-terminal route, but it doesn't work.

System.Posix.User's getLoginName calls the C function getlogin. This function, on GNU/Linux at least, looks in the file /var/run/utmp for a login record with a tty name that matches that of the terminal connected to stdin (filedescriptor 0).

It is possible to trick getlogin to check a pseudo terminal's name with something like:

(master, slave) <- openPseudoTerminal
dupTo master stdInput

But, as far as I understand, pseudo-terminals are never registered in /var/run/utmp. Therefore getlogin will not find the user's login name and just return 'No such file or directory'. Maybe better than 'Inappropriate ioctl for device', but still an error.

What does work, surprisingly, is adding this to user001.hs:

dupTo stdOutput stdInput

, but only if we wouldn't redirect stdout as well. The same for stderr.

The solution is to simply not redirect stdin (i.e. don't do ./user001 < /dev/null). This implies skipping the ghci way. The commit that introduced the no_stdin test option alluded to this as well: fa52a8c9d8eae5e3fc4c0cf0e5672875e161e05c.

One general concern is that there are no guarantees that getlogin will return anything other than NULL, so the test with this patch applied might fail on some systems. Another option therefore would be to turn the getLoginName test back off again, document why, and close this issue regardless.

Review of patch requested.

Last edited 11 months ago by thomie (previous) (diff)

comment:20 Changed 11 months ago by thomie

  • Milestone 7.6.2 deleted
  • Status changed from new to patch
  • Version 6.6.1 deleted

comment:21 Changed 11 months ago by thomie

comment:22 Changed 10 months ago by thomie

  • Resolution set to fixed
  • Status changed from patch to closed

Merged in unix package:

Enable test for getLoginName

Fixes #1487.

Make use of no_stdin test option, introduced explictly for this purpose
in fa52a8c9d8eae5e3fc4c0cf0e5672875e161e05c

comment:23 Changed 9 months ago by ezyang

  • Owner thomie deleted
  • Resolution fixed deleted
  • Status changed from closed to new

Hello, the test is still failing for me, using GHC HEAD and the latest version of unix:

=====> user001(normal) 5 of 29 [0, 0, 0]
cd . && '/5playpen/t-edyang/ghc-master/inplace/bin/ghc-stage2' -fforce-recomp -dcore-lint -dcmm-lint -dno-debug-output -no-user-package-db -rtsopts -fno-ghci-history -o user001 user001.hs  -package unix  >user001.comp.stderr 2>&1
cd . && ./user001    >user001.run.stdout 2>user001.run.stderr
Actual stdout output differs from expected:
--- ./user001.stdout    2014-08-22 23:28:41.969906580 +0100
+++ ./user001.run.stdout        2014-08-23 00:33:07.631841764 +0100
@@ -3,11 +3,11 @@
 getEffectiveUserID: OK
 getEffectiveGroupID: OK
 getGroups: OK
-getLoginName: OK
+getLoginName: ERROR: getLoginName: does not exist (No such file or directory)
 getEffectiveUserName: OK
 getGroupEntryForID: OK
 getGroupEntryForName: OK
 getAllGroupEntries: OK
 getUserEntryForID: OK
-getUserEntryForName: OK
+getUserEntryForName: ERROR: getLoginName: does not exist (No such file or directory)
 getAllUserEntries: OK
*** unexpected failure for user001(normal)

Unexpected results from:
TEST="user001"

On my box, running the following C program in terminal returns null:

#include <stdio.h>
#include <unistd.h>
int main() {
    printf("%p\n", getlogin());
}

This StackOverflow post suggests that getlogin works quite unreliably: http://stackoverflow.com/questions/4785126/getlogin-c-function-returns-null-and-error-no-such-file-or-directory

comment:24 Changed 9 months ago by thomie

@ezyang: which terminal emulator are you using? Does it work with xterm?

Maybe we should change the signature of getLoginName to:

getLoginName :: IO (Maybe String)

, since the man page explicitly mentions that getlogin can return NULL:

getlogin() returns a pointer to a string containing the name of the
user logged in on the controlling terminal of the process, or a NULL
pointer if this information cannot be determined.

The same applies to getGroupEntryForID, ticket #8293.

comment:25 Changed 9 months ago by ezyang

From a cygwin terminal, I am moshed into a screen session. I can't easily test xterm because I don't have X forwarding.

comment:26 Changed 8 months ago by thomie

A library proposal to solve this. The test has been disabled again for the time being.

comment:27 Changed 8 months ago by thoughtpolice

  • Component changed from libraries/unix to Core Libraries
  • Owner set to ekmett

Moving over to new owning component 'Core Libraries'.

comment:28 Changed 3 months ago by argiopeweb

  • Cc core-libraries-committee@… added
Note: See TracTickets for help on using tickets.