Is a new process needed for a new pam(_systemd) session? - linux

As an Experiment I am writing a small linux display manager. As references, I use lightdm, especially https://github.com/canonical/lightdm/blob/master/src/session-child.c, and the systemd documentation page https://www.freedesktop.org/wiki/Software/systemd/writing-display-managers/ .
For the start, it allways manages tty9, and restarting after logout is handled by systemd (Restart=always).
So what the program does is
show the login prompt (the "greeter" session)
start pam session for greeter
pam_authenticate the user
end pam session for greeter
start the user session.
start pam session for user
fork, switch user, cd, exec
Lightdm uses two session-child process for this, but for simplicity I tried to do it in one.
When I comment out the session start for the "greeter", like here: https://github.com/TheJonny/textdm/blob/ba32d87f23816ef78763016b4c748a0875ae93f6/src/main.rs#L86, I am able to log in and start weston (starting the X server is currently not finished). If I do use a session for the greeter (lines 86 and 126 enabled), pam_systemd fails with the debug messages
Feb 23 01:30:09 io textdm[4084383]: pam_systemd(textdm:session): Asking logind to create session: uid=1001 pid=4084383 service=textdm type=wayland class=user desktop= seat=seat0 vtnr=9 tty>
Feb 23 01:30:09 io textdm[4084383]: pam_systemd(textdm:session): Session limits: memory_max=n/a tasks_max=n/a cpu_weight=n/a io_weight=n/a runtime_max_sec=n/a
Feb 23 01:30:09 io textdm[4084383]: pam_systemd(textdm:session): Not creating session: Already running in a session or user slice
It does not show up in loginctl, does not set $XDG_RUNTIME_DIR, and then weston failes to start.
So my question is: can this (only) be solved by using separete processes? Is there another way to fully tear down the pam_systemd session?
(I am using the pam-client binding for rust, https://docs.rs/pam-client/0.2.0/pam_client/struct.Context.html#method.open_session should call pam_open_session() and pam_setcred(), and the drop should close the session and credentials.)

to clean up, I answer my question.
https://github.com/systemd/systemd/blob/756755d0fc5a0ef380416a54346b6438c3fb7ba5/src/login/pam_systemd.c#L1020
pam_systemd intentionally leaks a pipe file descriptor, and logind delays closing the session until this is closed, that is until the process using pam_systemd has exited.

Related

Is perforce "connection reset by peer" error really an error ?

P4 Server version: P4D/LINUX26X86_64/2013.2/938876 (2014/09/23)
on RHEL6
While running a perl script using p4perl, I trap an error something like this...
if ($p4->ErrorCount() {
foreach $err ($p4->Errors) {
print "$err\n";
}
}
These errors pop up in a nondeterministic way, sometimes I get them, sometimes not. But if I trap an error with the code above, and I get ...
TCP receive failed.
read: socket:
Connection reset by peer
Is that a real error (given that, apparently, the connection was reset ?)
Can I ignore this? Will it run the thing I wanted to run after resetting the connection ? Or do I need to rerun that command ?
I fear that the problem may be rooted in the fact that the perl script does a fork earlier on and the $p4 handle I have was sent to the forked process. Could I do something like this to detect and remedy this
use P4;
our $p4 = new P4;
<perl forks off a new process...>
if(!($p4-IsConnected)) {
$p4->SetCwd("$CWD");
if($p4->ErrorCount()) {handle_p4_error();}
$p4->Connect();
if($p4->ErrorCount()) {handle_p4_error();}
}
....etc....
exit;
sub handle_p4_err {
print "<<<P4 ERROR>>>\n";
foreach $err ($p4->Errors) {
print "$err\n";
}
exit;
}
Or will the SetCwd fail for lack of connection?
Could the P4 admin be setting some sort of timeout (kill connection after x minutes of inactivity) ?
Thanks for any help !
Is that a real error (given that, apparently, the connection was reset ?)
Yes; the connection with the server was terminated.
Can I ignore this? Will it run the thing I wanted to run after resetting the connection?
No.
Or do I need to rerun that command ?
Yes; I think you will also need to reopen the connection first.
$p4->Connect();
if($p4->ErrorCount()) {handle_p4_error();}
That is the general pattern, although if the connection fails you probably want to bail out since nothing you do after that point is going to work (and in most cases it means something is configured wrong).
Or will the SetCwd fail for lack of connection?
No; that's purely a client side action and does not talk to the server.
Could the P4 admin be setting some sort of timeout (kill connection after x minutes of inactivity) ?
That is one possibility -- does your script hold an idle connection open? That's considered poor manners since enough of those will constitute a DDoS attack by preventing any new connections from being opened. Another possibility is that there was some other network failure (your VPN connection went down, etc).
In my particular case, I believe the problem had to do with the fork in the perl script. Perhaps the handle was passed to the forked process and this interfered with attempts to reconnect in the main process thread. I had a similar problem with a DB connection. The remedy was similar as well....
What seemed to work was to unconditionally disconnect from P4 just before the fork and unconditionally reconnect right after. The forked process didn't need a P4 connection, so this is OK (in my particular case).
In my case, the problem was I needed to make an ssh connection to the perforce server, but I hadn't added the correct ssh key. You can list ssh keys added to your session with this command:
ssh-add -L

How to send "CTRL+C" to child process in Node.js?

I tried to spawn child process - vvp (https://linux.die.net/man/1/vvp). At the certain time, I need to send CTRL+C to that process.
I am expecting that simulation will be interrupted and I get the interactive prompt. And after that I can continue the simulation by send command to the child process.
So, I tried something like this:
var child = require('child_process');
var fs = require('fs');
var vcdGen = child.spawn('vvp', ['qqq'], {});
vcdGen.stdout.on('data', function(data) {
console.log(data.toString())
});
setTimeout(function() {
vcdGen.kill('SIGINT');
}, 400);
In that case, a child process was stopped.
I also tried vcdGen.stdin.write('\x03') instead of vcdGen.kill('SIGINT'); but it isn't work.
Maybe it's because of Windows?
Is there any way to achieve the same behaviour as I got in cmd?
kill only really supports a rude process kill on Windows - the application signal model in Windows and *nix isn't compatible. You can't pass Ctrl+C through standard input, because it never comes through standard input - it's a function of the console subsystem (and thus you can only use it if the process has an attached console). It creates a new thread in the child process to do its work.
There's no supported way to do this programmatically. It's a feature for the user, not the applications. The only way to do this would be to do the same thing the console subsystem does - create a new thread in the target application and let it do the signalling. But the best way would be to simply use coöperative signalling instead - though that of course requires you to change the target application to understand the signal.
If you want to go the entirely unsupported route, have a look at https://stackoverflow.com/a/1179124/3032289.
If you want to find a middle ground, there's a way to send a signal to yourself, of course. Which also means that you can send Ctrl+C to a process if your consoles are attached. Needless to say, this is very tricky - you'd probably want to create a native host process that does nothing but create a console and run the actual program you want to run. Your host process would then listen for an event, and when the event is signalled, call GenerateConsoleCtrlEvent.

Close another process from node on Windows

How can I kill a process from node on Windows?
I'm making a updater. It needs close a windows executable (.exe) to download the updates. (The update process is download and overwrite). I read that this is possible with process.kill(pid[, signal])
But, How can I get the PID of the process if I know the name of the process?
According to the documentation, you simply access the property.
process.kill(process.pid, 'SIGKILL');
This is a theoretical, untested, psuedo function that may help explain what I have in mind
exec('tasklist', (err, out, code) => { //tasklist is windows, but run command to get proccesses
const id = processIdFromTaskList(processName, out); //get process id from name and parse from output of executed command
process.kill(id, "SIGKILL"); //rekt
});
Use node-windows to get pid of process you want to kill so that you can call process.kill. The library also provides an api to kill task.

PHP Session expiring and system force logout

When i left system is in idle mode( means inactive mode) , and when i come to access system after 1 or 2 hours, system reacts well when i use single window but when i generate recieppt through ajax and open the receipt in window.popup window then the system logs out. and redirect to login page because session expired in idle mode , even if i set the session for lifetime,
case '1':
$_SESSION['kid'] = $q4['id'];
ini_set('session.gc_maxlifetime', 100*60*60);
session_set_cookie_params(0,"/");
break;
plese help ......
ini_set('session.gc_maxlifetime', ...) should be called before session_start()

libspotify: logging out or releasing session causes crash

This is in response to dan's (dan^spotify on IRC) offer to take a look at my testcase, but I post it here in case anyone has encountered similar issues.
I'm experiencing a problem with libspotify where the application crashes (memory access violation) in both of these two scenarios:
the first sp_session_process_events (triggered by notify main thread callback) that's called after the sp_session_logout() function is called crashes the application
skipping logout and calling sp_session_release() crashes the application
I've applied sufficient synchronization from the session callbacks, and I'm otherwise operating on a single thread.
I've made a small testcase that does the following:
Creates session
Logs in
Waits 10 seconds
Attempts to logout, upon which it crashes (when calling sp_session_process_events())
If it were successful in logging out (which it isn't), would call sp_session_release()
I made a Gist for the testcase. It can be found here: https://gist.github.com/4496396
The test case is made using Qt (which is what I'm using for my project), so you'd need Qt 5 to compile it. I've also only written it with Windows and Linux in mind (don't have Mac). Assuming you have Qt 5 and Qt Creator installed, the instructions are as follows:
Download the gist
Copy the libspotify folder into the same folder as the .pro file
Copy your appkey.c file into the same folder
Edit main.cpp to login with your username and password
Edit line 38-39 in sessiontest.cpp and set the cache and settings path to your liking
Open up the .pro file and run from Qt Creator
I'd be very grateful if someone could tell me what I'm doing wrong, as I've spent so many hours trying anything I could think of or just staring at it, and I fear I've gone blind to my own mistakes by now.
I've tested it on both Windows 7 and Linux Ubuntu 12.10, and I've found some difference in behavior:
On Windows, the testcase crashes invariably regardless of settings and cache paths.
On Linux, if setting settings and cache to "" (empty string), logging out and releasing the session works fine.
On Linux, if paths are anything else, the first run (when folder does not already exist) logs out and releases session as it should, but on the next run (when folder already exists), it crashes in the exact same way as it does on Windows.
Also, I can report that sp_session_flush_caches() does not cause a crash.
EDIT: Also, hugo___ on IRC was kind enough to test it on OSX for me. He reported no crashes despite running the application several times in a row.
While you very well may be looking at a bug in libspotify, I'd like to point out a possibly redundant call to sp_session_process_events(), from what I gathered from looking at your code.
void SessionTest::processSpotifyEvents()
{
if (m_session == 0)
{
qDebug() << "Process: No session.";
return;
}
int interval = 0;
sp_session_process_events(m_session, &interval);
qDebug() << interval;
m_timerId = startTimer(interval);
}
It seems this code will pickup the interval value and start a timer on that to trigger a subsequent call to event(). However, this code will also call startTimer when interval is 0, which is strictly not necessary, or rather means that the app can go about doing other stuff until it gets a notify_main_thread callback. The docs on startTimer says "If interval is 0, then the timer event occurs once every time there are no more window system events to process.". I'm not sure what that means exactly but it seems like it can produce at least one redundant call to sp_session_process_events().
http://qt-project.org/doc/qt-4.8/qobject.html#startTimer
I notice that you will get a crash on sp_session_release if you have a track playing when you call it.
I have been chasing this issue today. Login/logout works just fine on Mac, but the issue was 100% repeatable as you described on Windows.
By registering empty callbacks for offline_status_updated and credentials_blob_updated, the crash went away. That was a pretty unsatisfying fix, and I wonder if any libspotify developers want to comment on it.
Callbacks registered in my app are:
logged_in
logged_out
notify_main_thread
log_message
offline_status_updated
credentials_blob_updated
I should explicitly point out that I did not try this on the code you supplied. It would be interesting to know if adding those two extra callbacks works for you. Note that the functions I supply do absolutely nothing. They just have to be there and be registered when you create the session.
Adding the following call in your "logged in" libspotify callback seems to fix this crash as detailed in this SO post:
sp_session_playlistcontainer(session);

Resources